Spring AOP Demo

AOP概念真多,先通过一个Demo学习一下

首先定义一个接口和两个方法

package com.lihuia;

/**
* Copyright (C), 2018-2019
* FileName: Hello
* Author: lihui
* Date: 2019/2/4
*/

public interface Hello {

void sayHello();
void doPrint();
}

接口的两个实现类

HelloImpl1

package com.lihuia;

/**
* Copyright (C), 2018-2019
* FileName: HelloImplA
* Author: lihui
* Date: 2019/2/4
*/

public class HelloImplA implements Hello {

@Override
public void sayHello() {
System.out.println("HelloImplA: sayHello");
}

@Override
public void doPrint() {
System.out.println("HelloImplA: doPrint");
}
}

HelloImpl2

package com.lihuia;

/**
* Copyright (C), 2018-2019
* FileName: HelloImplB
* Author: lihui
* Date: 2019/2/4
*/

public class HelloImplB implements Hello {

@Override
public void sayHello() {
System.out.println("HelloImplB: sayHello");
}

@Override
public void doPrint() {
System.out.println("HelloImplB: doPrint");
}
}

打印时间

package com.lihuia;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* Copyright (C), 2018-2019
* FileName: TimeHandler
* Author: lihui
* Date: 2019/2/4
*/

public class TimeHandler {

public void printTime() {
System.out.println("CurrentTime: " +
new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss:SSS").format(new Date()));
}
}

下面通过XML文件完成AOP配置,在此之前POM里添加依赖

<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.1</version>
</dependency>

新增xml文件,这里的标签通过《Spring in Action》里AOP术语来说明

通知Advice

NewImage

切点Poincut和切片Aspect

NewImage

新增aop.xml配置,新增aop命名空间和配置

aop:pointcut定义了一个切点,expression里的方法在调用后就会就行切面;execution里第一个*代表返回值,这里表示返回任意类型,第二个*表示正则匹配,匹配包com.lihuia.Hello.*开头的类方法,(..)表示参数数量和类型任意

如此一来,com.lihuia.Hello包里任何类里的方法被调用,不论什么返回值,都会触发执行切面

aop:aspect定义了一个切面,ref引用了TimeHandler实例,pointcut-ref传入一个pointcut,关联切点,但是一个切点是可以关联多个切面的,一个切面只能关联一个方法,只要切点触发,就会执行切面的一些Advice通知,具体要执行的就是method里声明的方法

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

<bean id="timeHandler" class="com.lihuia.TimeHandler"></bean>

<aop:config>
<aop:aspect id="time" ref="timeHandler">
<aop:pointcut
id="addMethod"
expression="execution(* com.lihuia.Hello.*(..))"></aop:pointcut>
<aop:before
method="printTime"
pointcut-ref="addMethod"></aop:before>
<aop:after
method="printTime"
pointcut-ref="addMethod"></aop:after>
</aop:aspect>
</aop:config>
</beans>

最后新增测试类

package com.lihuia;

import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.Test;

import javax.annotation.Resource;

/**
* Copyright (C), 2018-2019
* FileName: AopTest
* Author: lihui
* Date: 2019/2/4
*/

@ContextConfiguration(locations = {
"classpath*:aop.xml"
})
public class AopTest extends AbstractTestNGSpringContextTests {

@Resource
private Hello helloImplA;

@Resource
private Hello helloImplB;

@Test(description = "AOP测试")
public void aopTest() {
System.out.println("#######################################");
helloImplA.sayHello();
System.out.println("#######################################");
helloImplA.doPrint();
System.out.println("#######################################");
helloImplB.sayHello();
System.out.println("#######################################");
helloImplB.doPrint();
System.out.println("#######################################");
}
}

由于IOC注入实现类对象实例化,因此新增两个bean对象

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

<bean id="helloImplA" class="com.lihuia.HelloImplA"></bean>
<bean id="helloImplB" class="com.lihuia.HelloImplB"></bean>
<bean id="timeHandler" class="com.lihuia.TimeHandler"></bean>

<aop:config>
<aop:aspect id="time" ref="timeHandler">
<aop:pointcut
id="addMethod"
expression="execution(* com.lihuia.Hello.*(..))"></aop:pointcut>
<aop:before
method="printTime"
pointcut-ref="addMethod"></aop:before>
<aop:after
method="printTime"
pointcut-ref="addMethod"></aop:after>
</aop:aspect>
</aop:config>
</beans>

输出结果

#######################################
CurrentTime: 2019-02-09-23:20:42:267
HelloImplA:  sayHello
CurrentTime: 2019-02-09-23:20:42:272
#######################################
CurrentTime: 2019-02-09-23:20:42:273
HelloImplA:  doPrint
CurrentTime: 2019-02-09-23:20:42:275
#######################################
CurrentTime: 2019-02-09-23:20:42:276
HelloImplB:  sayHello
CurrentTime: 2019-02-09-23:20:42:276
#######################################
CurrentTime: 2019-02-09-23:20:42:277
HelloImplB:  doPrint
CurrentTime: 2019-02-09-23:20:42:277
#######################################

每个pointcut都会触发aspect里method的调用

发表回复