Spring從@Aspect到Advisor使用演示實(shí)例
演示1 - 代理創(chuàng)建器
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 // 創(chuàng)建 -> (*) 依賴注入 -> 初始化 (*) context.refresh(); // for (String name : context.getBeanDefinitionNames()) { // System.out.println(name); // } /* 第一個(gè)重要方法 findEligibleAdvisors 找到有【資格】的 Advisors a. 有【資格】的 Advisor 一部分是低級(jí)的, 可以由自己編寫(xiě), 如下例中的 advisor3 b. 有【資格】的 Advisor 另一部分是高級(jí)的, 由本章的主角解析 @Aspect 后獲得 */ AnnotationAwareAspectJAutoProxyCreator creator = context.getBean(AnnotationAwareAspectJAutoProxyCreator.class); List<Advisor> advisors = creator.findEligibleAdvisors(Target2.class, "target2"); /*for (Advisor advisor : advisors) { System.out.println(advisor); }*/ /* 第二個(gè)重要方法 wrapIfNecessary a. 它內(nèi)部調(diào)用 findEligibleAdvisors, 只要返回集合不空, 則表示需要?jiǎng)?chuàng)建代理 */ 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(); /* 學(xué)到了什么 a. 自動(dòng)代理后處理器 AnnotationAwareAspectJAutoProxyCreator 會(huì)幫我們創(chuàng)建代理 b. 通常代理創(chuàng)建的活在原始對(duì)象初始化后執(zhí)行, 但碰到循環(huán)依賴會(huì)提前至依賴注入之前執(zhí)行 c. 高級(jí)的 @Aspect 切面會(huì)轉(zhuǎn)換為低級(jí)的 Advisor 切面, 理解原理, 大道至簡(jiǎn) */ } static class Target1 { public void foo() { System.out.println("target1 foo"); } } static class Target2 { public void bar() { System.out.println("target2 bar"); } } @Aspect // 高級(jí)切面類(lèi) @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 // 低級(jí)切面 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 的作用
- 將高級(jí) @Aspect 切面統(tǒng)一為低級(jí) Advisor 切面
- 在合適的時(shí)機(jī)創(chuàng)建代理
findEligibleAdvisors 找到有【資格】的 Advisors
- 有【資格】的 Advisor 一部分是低級(jí)的, 可以由自己編寫(xiě), 如本例 A17 中的 advisor3
- 有【資格】的 Advisor 另一部分是高級(jí)的, 由解析 @Aspect 后獲得
wrapIfNecessary
- 它內(nèi)部調(diào)用 findEligibleAdvisors, 只要返回集合不空, 則表示需要?jiǎng)?chuàng)建代理
- 它的調(diào)用時(shí)機(jī)通常在原始對(duì)象初始化后執(zhí)行, 但碰到循環(huán)依賴會(huì)提前至依賴注入之前執(zhí)行
演示2 - 代理創(chuàng)建時(shí)機(jī)
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(); // 創(chuàng)建 -> (*) 依賴注入 -> 初始化 (*) /* 學(xué)到了什么 a. 代理的創(chuàng)建時(shí)機(jī) 1. 初始化之后 (無(wú)循環(huán)依賴時(shí)) 2. 實(shí)例創(chuàng)建后, 依賴注入前 (有循環(huán)依賴時(shí)), 并暫存于二級(jí)緩存 b. 依賴注入與初始化不應(yīng)該被增強(qiáng), 仍應(yīng)被施加于原始對(duì)象 */ } @Configuration static class Config { @Bean // 解析 @Aspect、產(chǎn)生代理 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 MethodInterceptor 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 public 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()"); } } }
收獲??
代理的創(chuàng)建時(shí)機(jī)
- 初始化之后 (無(wú)循環(huán)依賴時(shí))
- 實(shí)例創(chuàng)建后, 依賴注入前 (有循環(huán)依賴時(shí)), 并暫存于二級(jí)緩存
依賴注入與初始化不應(yīng)該被增強(qiáng), 仍應(yīng)被施加于原始對(duì)象
演示3 - @Before 對(duì)應(yīng)的低級(jí)通知
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 { AspectInstanceFactory factory = new SingletonAspectInstanceFactory(new Aspect()); // 高級(jí)切面轉(zhuǎn)低級(jí)切面類(lèi) List<Advisor> list = new ArrayList<>(); for (Method method : Aspect.class.getDeclaredMethods()) { if (method.isAnnotationPresent(Before.class)) { // 解析切點(diǎn) String expression = method.getAnnotation(Before.class).value(); AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); pointcut.setExpression(expression); // 通知類(lèi) 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 前置通知會(huì)被轉(zhuǎn)換為下面原始的 AspectJMethodBeforeAdvice 形式, 該對(duì)象包含了如下信息 a. 通知代碼從哪兒來(lái) b. 切點(diǎn)是什么(這里為啥要切點(diǎn), 后面解釋) c. 通知對(duì)象如何創(chuàng)建, 本例共用同一個(gè) Aspect 對(duì)象 類(lèi)似的通知還有 1. AspectJAroundAdvice (環(huán)繞通知) 2. AspectJAfterReturningAdvice 3. AspectJAfterThrowingAdvice 4. AspectJAfterAdvice (環(huán)繞通知) */ } }
收獲??
@Before 前置通知會(huì)被轉(zhuǎn)換為原始的 AspectJMethodBeforeAdvice 形式, 該對(duì)象包含了如下信息
- 通知代碼從哪兒來(lái)
- 切點(diǎn)是什么(這里為啥要切點(diǎn), 后面解釋)
- 通知對(duì)象如何創(chuàng)建, 本例共用同一個(gè) Aspect 對(duì)象
類(lèi)似的還有
- AspectJAroundAdvice (環(huán)繞通知)
- AspectJAfterReturningAdvice
- AspectJAfterThrowingAdvice (環(huán)繞通知)
- AspectJAfterAdvice (環(huán)繞通知)
到此這篇關(guān)于Spring從@Aspect到Advisor使用演示實(shí)例的文章就介紹到這了,更多相關(guān)Spring @Aspect Advisor內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Java的Struts框架以及相關(guān)的MVC設(shè)計(jì)理念
這篇文章主要介紹了詳解Java的Struts框架以及相關(guān)的MVC設(shè)計(jì)理念,Struts是Java的SSH三大web開(kāi)發(fā)框架之一,需要的朋友可以參考下2015-12-12Java的Synchronized關(guān)鍵字學(xué)習(xí)指南(全面 & 詳細(xì))
這篇文章主要給大家介紹了關(guān)于Java的Synchronized關(guān)鍵字的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03Java實(shí)現(xiàn)ModbusTCP通信功能
使用ModbusTCP實(shí)現(xiàn)和硬件設(shè)備通信功能,本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-08-08springboot項(xiàng)目組引入JMeter的實(shí)現(xiàn)步驟
本文主要介紹了springboot項(xiàng)目組引入JMeter的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09java書(shū)店系統(tǒng)畢業(yè)設(shè)計(jì) 用戶模塊(2)
這篇文章主要介紹了java書(shū)店系統(tǒng)畢業(yè)設(shè)計(jì),第二步系統(tǒng)總體設(shè)計(jì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10