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
切点Poincut和切片Aspect
新增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的调用