Spring 引介增強IntroductionAdvisor使用
作者:FastCoder
在不修改業務代碼的情況下如何讓某個類具有某項功能呢,比如具有XXXDAO接口的能力?IntroductionAdvisor只能應用于Introduction類型的通知,而PointcutAdvisor可以應用于所有類型的通知
環境:Spring5.2.14
在不修改業務代碼的情況下如何讓某個類具有某項功能呢,比如具有XXXDAO接口的能力?
1 IntroductionAdvisor介紹
IntroductionAdvisor與PointcutAdvisor區別
- IntroductionAdvisor只能應用于類級別
- IntroductionAdvisor只能應用于Introduction類型的通知,而PointcutAdvisor可以應用于所有類型的通知
- IntroductionAdvisor的Advice需要實現目標的接口,而pintcutAdvisor中的Advice沒有改要求
2 IntroductionAdvisor使用流程
假定我們的業務類CustomDAO希望具有DesignDAO(接口)的能力
2.1 目標接口
- public interface DesignDAO {
- public void design() ;
- }
2.2 Introduction攔截器
- public class CustomIntroductionInterceptor implements IntroductionInterceptor, DesignDAO {
- // 判斷當前的攔截器是否實現了目標接口(DesignDAO,我們需要某個類具有指定接口的功能)
- @Override
- public boolean implementsInterface(Class<?> intf) {
- return intf.isAssignableFrom(this.getClass()) ;
- }
- @Override
- public Object invoke(MethodInvocation invocation) throws Throwable {
- System.out.println("我是通知類:IntroductionInterceptor") ;
- // 判斷當前執行的方法所屬類是否實現了目標接口
- // 這里必須要進行相應的判斷攔截,否則會在沒有被攔截的類方法執行的時候報錯我
- // 因為你的其它類所對應的接口并沒有在該攔截器中被實現。
- if (implementsInterface(invocation.getMethod().getDeclaringClass())) {
- return invocation.getMethod().invoke(this, invocation.getArguments()) ;
- }
- return invocation.proceed() ;
- }
- @Override
- public void design() {
- System.out.println("接口實現了") ;
- }
- }
2.3 IntroductionAdvisor定義
- @Component
- public class CustomIntroductionAdvisor implements IntroductionAdvisor {
- // 定義Advice通知
- @Override
- public Advice getAdvice() {
- return new CustomIntroductionInterceptor() ;
- }
- // 該方法沒有被使用,建議直接返回true
- @Override
- public boolean isPerInstance() {
- return true ;
- }
- // 定義了所要實現的所有接口
- @Override
- public Class<?>[] getInterfaces() {
- return new Class<?>[] {DesignDAO.class} ;
- }
- // 過濾類,返回true就會被匹配
- @Override
- public ClassFilter getClassFilter() {
- return new ClassFilter() {
- @Override
- public boolean matches(Class<?> clazz) {
- return CustomDAO.class.isAssignableFrom(clazz) ;
- }
- } ;
- }
- // 在這里我們可以校驗我們的Advice類是否實現了執行的接口getInterfaces中定義的接口
- @Override
- public void validateInterfaces() throws IllegalArgumentException {
- // 這里可以參考DefaultIntroductionAdvisor的實現
- }
- }
這里可以查看示例文檔37示例源碼是如何執行的
2.4 驗證
- @Component
- public class CustomerDAOImpl implements CustomDAO {
- public void update() {
- System.out.println("更新數據..." + this.getClass()) ;
- }
- public void save() {
- System.out.println("保存方法..." + this.getClass()) ;
- }
- }
業務類并沒有實現DesignDAO接口。接下來看看通過上面定義IntroductionAdvisor是否可以讓我們的業務類具有目標類的功能
- public class LauncherMain {
- public static void main(String[] args) {
- System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true") ;
- AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("com.pack") ;
- CustomDAO dao = ctx.getBean(CustomDAO.class) ;
- System.out.println(dao.getClass()) ;
- System.out.println(Arrays.toString(dao.getClass().getInterfaces())) ;
- dao.save() ;
- dao.update() ;
- if (DesignDAO.class.isAssignableFrom(dao.getClass())) {
- DesignDAO ddao = (DesignDAO) dao ;
- System.out.println("IntroductionAdvisor start...") ;
- ddao.design() ;
- System.out.println("IntroductionAdvisor end...") ;
- }
- ctx.close() ;
- }
- }
執行結果:
- class com.sun.proxy.$Proxy14
- [interface com.pack.dao.CustomDAO, interface com.pack.interfaces.DesignDAO, interface org.springframework.aop.SpringProxy, interface org.springframework.aop.framework.Advised, interface org.springframework.core.DecoratingProxy]
- 我是通知類:IntroductionInterceptor, interface com.pack.dao.CustomDAO
- intf: interface com.pack.dao.CustomDAO
- 我被調用了...
- 保存方法...class com.pack.dao.CustomerDAOImpl
- 我是通知類:IntroductionInterceptor, interface com.pack.dao.CustomDAO
- intf: interface com.pack.dao.CustomDAO
- 更新數據...class com.pack.dao.CustomerDAOImpl
- IntroductionAdvisor start...
- 我是通知類:IntroductionInterceptor, interface com.pack.interfaces.DesignDAO
- intf: interface com.pack.interfaces.DesignDAO
- 接口實現了
- IntroductionAdvisor end...
責任編輯:姜華
來源:
今日頭條