Spring从@Aspect到Advisor使用演示实例
演示1 - 代理创建器
public class A17 { public static void main(String[] args) { GenericApplicationContext context = new GenericApplicationContext(); context.registerBean("ASPect1", Aspect1.class); context.registerBean("config", Config.class); context.registerBean(ConfigurationClassPostProcessor.class); context.registerBean(AnnotationAwareAspectJAutoProxyCreator.class); // BeanPostProcessor // 创建 -> (*) 依赖注入 -> 初始化 (*) context.refresh(); // for (String name : context.getBeanDefinitionNames()) { // System.out.println(name); // } /* 第一个重要方法 findEligibleAdvisors 找到有【资格】的 Advisors a. 有【资格】的 Advisor 一部分是低级的, 可以由自己编写, 如下例中的 advisor3 b. 有【资格】的 Advisor 另一部分是高级的, 由本章的主角解析 @Aspect 后获得 */ AnnotationAwareAspectJAutoProxyCreator creator = context.getBean(AnnotationAwareAspectJAutoProxyCreator.class); List<Advisor> advisors = creator.findEligibleAdvisors(Target2.class, "target2"); /*for (Advisor advisor : advisors) { System.out.println(advisor); }*/ /* 第二个重要方法 wrapIfNecessary a. 它内部调用 findEligibleAdvisors, 只要返回集合不编程客栈空, 则表示需要创建代理 */ Object o1 = creator.wrapIfNecessary(new Target1(), "target1", "target1"); System.out.println(o1.getClass()); Object o2 = creator.wrapIfNecessary(new Target2(), "target2", "target2"); System.out.println(o2.getClass()); ((Target1) o1).foo(); /* 学到了什么 a. 自动代理后处理器 AnnotationAwareAspectJAutoProxyCreator 会帮我们创建代理 b. 通常代理创建的活在原始对象初始化后执行, 但碰到循环依赖会提前至依赖注入之前执行 c. 高级的 @Aspect 切面会转换为低级的 Advisor 切面, 理解原理, 大道至简 */ } static class Target1 { public void foo() { System.out.println("target1 foo"); } } static class Target2 { public void bar() { System.out.println("target2 bar"); } } @Aspect // 高级切面类 @Order(1) static class Aspect1 { @Before("execution(* foo())") public void before1() { System.out.println("aspect1 before1..."); } @Before("execution(* foo())") public void before2() { System.out.println("aspect1 before2..."); } } @Configuration static class Config { /*@Bean // 低级切面 public Advisor advisor3(MethodInterceptor advice3) { AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); pointcut.setExpression("execution(* foo())"); DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice3); return advisor; } @Bean public MethodInterceptor advice3() { return invocation -> { System.out.println("advice3 before..."); Object result = invocation.proceed(); System.out.println("advice3 after..."); return result; }; }*/ } }
收获
AnnotationAwareAspectJAutoProxyCreator 的作用
- 将编程高级 @Aspect 切面统一为低级 Advisor 切面
- 在合适的时机创建代理
findEligibleAdvisors 找到有【资格】的 Advisors
- 有【资格】的 Advisor 一部分是低级的, 可以由自己编写, 如本例 A17 中的 advisor3
- 有【资格】的 Advisor 另一部分是高级的, 由解析 @Aspect 后获得
wrapIfNecessary
- 它内部调用 findEligibleAdvisors, 只要返回集合不空, 则表示需要创建代理
- 它的调用时机通常在原始对象初始化后执行, 但碰到循环依赖会提前至依赖注入之前执行
演示2 - 代理创建时机
public class A17_1 { public static void main(String[] args) { GenericApplicationContext context = new GenericApplicationContext(); context.registerBean(ConfigurationClassPostProcessor.class); context.registerBean(Config.class); context.refresh(); context.close(); // 创建 -> (*) 依赖注入 -> 初始化 (*) /* 学到了什么 a. 代理的创建时机 1. 初始化之后 (无循环依赖时) 2. 实例创建后, 依赖注入前 (有循环依赖时), 并暂存于二级缓存 b. 依赖注入与初始化不应该被增强, 仍应被施加于原始对象 */ } @Configuration static class Config { @Bean // 解析 @Aspect、产生代理 public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator() { return new AnnotationAwareAspectJAutoProxyCreator(); } @Bean // 解析 @Autowired public AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor() { return new AutowiredAnnotationBeanPostProcessor(); } @Bean // 解析 @PostConstruct public CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor() { return new CommonAnnotationBeanPostProcessor(); } @Bean public Advisor advisor(MethodInterceptor advice) { AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); pointcut.setExpression("execution(* foo())"); return new DefaultPointcutAdvisor(pointcut, advice); } @Bean public MethodIandroidnterceptor advice() { return (MethodInvocation invocation) -> { System.out.println("before..."); return invocation.proceed(); }; } @Bean public Bean1 bean1() { return new Bean1(); } @Bean public Bean2 bean2() { return new Bean2(); } } static class Bean1 { public void foo() { } public Bean1() { System.out.println("Bean1()"); } @Autowired public void setBean2(Bean2 bean2) { System.out.println("Bean1 setBean2(bean2) class is: " + bean2.getClass()); } @PostConstruct p编程客栈ublic void init() { System.out.println("Bean1 init()"); } } static class Bean2 { public Bean2() { System.out.println("Bean2()"); } @Autowired public void setBean1(Bean1 bean1) { System.out.println("Bean2 setBean1(bean1) class is: " + bean1.getClass()); } @PostConstruct public void init() { System.out.println("Bean2 init()"); } } }
收获
代理的创建时机
- 初始化之后 (无循环依赖时)
- 实例创建后, 依赖注入前 (有循环依赖时), 并暂存于二级缓存
依赖注入与初始化不应该被增强, 仍应被施加于原始对象
演示3 - @Before 对应的低级通知
public class A17_2 { static class Aspect { @Before("execution(* foo())") public void before1() { System.out.println("before1"); } @Before("execution(* foo())") public void before2() { System.out.println("before2"); } public void after() { System.out.println("after"); } public void afterReturning() { System.out.println("afterReturning"); } public void afterThrowing() { System.out.println("afterThrowing"); } public Object around(ProceedingJoinPoint pjp) throws Throwable { try { System.out.println("around...before"); return pjp.proceed(); } finally { System.out.println("around...after"); } } } static class Target { public void foo() { System.out.println("target foo"); } } @SuppressWarnings("all") public static void main(String[] args) throws Throwable { AspectInst开发者_开发入门anceFactory factory = new SingletonAspectInstanceFactory(new Aspect()); // 高级切面转低级切面类 List<Advisor> list = new ArrayList<>(); for (Method method : Aspect.class.getDeclaredMethods()) { if (method.isAnnotationPresent(Before.class)) { // 解析切点 String expression = method.getAnnotation(Before.class).value(); AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); pointcut.setExpression(expression); // 通知类 AspectJMethodBeforeAdvice advice = new AspectJMethodBeforeAdvice(method, pointcut, factory); // 切面 Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice); list.add(advisor); } } for (Advisor advisor : list) { System.out.println(advisor); } /* @Before 前置通知会被转换为下面原始的 AspectJMethodBeforeAdvice 形式, 该对象包含了如下信息 a. 通知代码从哪儿来 b. 切点是什么(这里为啥要切点, 后面解释) c. 通知对象如何创建, 本例共用同一个 Aspect 对象 类似的通知还有 1. AspectJAroundAdvice (环绕通知) 2. AspectJAfterReturningAdvice 3. AspectJAfterThrowingAdvice 4. AspectJAfterAdvice (环绕通知) */ } }
收获
@Before 前置通知会被转换为原始的 AspectJMethodBeforeAdvice 形式, 该对象包含了如下信息
- 通知代码从哪儿来
- 切点是什么(这里为啥要切点, 后面解释)
- 通知对象如何创建, 本例共用同一个 Aspect 对象
类似的还有
- AspectJAroundAdvice (环绕通知)
- AspectJAfterReturningAdvice
- AspectJAfterThrowingAdvice (环绕通知)
- AspectJAfterAdvice (环绕通知)
到此这篇关于Spring从@Aspect到Advisor使用演示实例的文章就介绍到这了,更多相关Spring @Aspect Advisor内容请搜索我们以前的文章或继续浏览下面的javascript相关文章希望大家以后多多支持我们!
精彩评论