上一节介绍了基于Schema的AOP,本篇介绍基于@AspectJ
的AOP。
1.@AspectJ切面
- 目标对象
package com.lyc.cn.v2.day07;
public interface Animal {
void sayHello();
}
package com.lyc.cn.v2.day07;
public class Dog implements Animal {
public void sayHello() {
System.out.println("--被增强的方法");
}
}
- 引介
package com.lyc.cn.v2.day07;
public interface IIntroduce {
void sayIntroduce();
}
package com.lyc.cn.v2.day07;
public class IntroduceImpl implements IIntroduce {
@Override
public void sayIntroduce() {
System.out.println("--引入");
}
}
- 切面
package com.lyc.cn.v2.day07;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
/**
* 切面类
* @author: LiYanChao
* @create: 2018-10-31 15:46
*/
@Aspect
public class DogAspect {
/**
* 例如:execution (* com.sample.service.impl..*.*(..)
* 1、execution(): 表达式主体。
* 2、第一个*号:表示返回类型,*号表示所有的类型。
* 3、包名:表示需要拦截的包名,后面的两个点表示当前包和当前包的所有子包,
* 即com.sample.service.impl包、子孙包下所有类的方法。
* 4、第二个*号:表示类名,*号表示所有的类。
* 5、*(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个点表示任何参数。
**/
@Pointcut("execution(* com.lyc.cn.v2.day07.*.*(..))")
public void test() {
}
@Before("test()")
public void beforeTest() {
System.out.println("==前置增强");
}
@After("test()")
public void afterTest() {
System.out.println("==后置最终增强");
}
@AfterThrowing("test()")
public void afterThrowingTest() {
System.out.println("==后置异常增强");
}
@AfterReturning("test()")
public void afterReturningTest() {
System.out.println("==后置返回增强");
}
@Around("test()")
public Object aroundTest(ProceedingJoinPoint p) {
System.out.println("==环绕增强开始");
Object o = null;
try {
o = p.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("==环绕增强结束");
return o;
}
@DeclareParents(value = "com.lyc.cn.v2.day07.Dog", defaultImpl = IntroduceImpl.class)
private IIntroduce iIntroduce;
}
- 配置文件
<?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.xsd">
<!--
1、proxy-target-class
如果被代理的目标对象至少实现了一个接口,则会使用JDK动态代理,所有实现该目标类实现的接口都将被代理
如果该目标对象没有实现任何接口,则创建CGLIB动态代理。
但是可以通过proxy-target-class属性强制指定使用CGLIB代理,
2、expose-proxy
解决目标对象内部的自我调用无法实施切面增强的问题
-->
<aop:aspectj-autoproxy proxy-target-class="true">
<!-- 指定@Aspect类,支持正则表达式,符合该表达式的切面类才会被应用-->
<aop:include name="dogAspect"></aop:include>
</aop:aspectj-autoproxy>
<!--bean-->
<bean id="dog" class="com.lyc.cn.v2.day07.Dog"/>
<!--AspectJ-->
<bean name="dogAspect" class="com.lyc.cn.v2.day07.DogAspect"/>
</beans>
- 测试及结果
package com.lyc.cn.v2.day07;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test1() {
// 基于@AspectJ注解方式
ApplicationContext ctx = new ClassPathXmlApplicationContext("v2/day07.xml");
Dog dog = ctx.getBean("dog", Dog.class);
dog.sayHello();
}
@Test
public void test2() {
// 引入
ApplicationContext ctx = new ClassPathXmlApplicationContext("v2/day07.xml");
// 注意:getBean获取的是dog
IIntroduce introduce = ctx.getBean("dog", IIntroduce.class);
introduce.sayIntroduce();
}
}
// 测试一
==环绕增强开始
==前置增强
--被增强的方法
==环绕增强结束
==后置最终增强
==后置返回增强
// 测试二
--引入
2.总结
前篇和本篇主要还是回顾了SpringAop的使用方式,也为了接下来的源码分析做好测试类准备,在接下来的分析中主要讲解以@AspectJ
方式的实现方式。