上一节介绍了基于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
方式的实现方式。