Spring 引介增強(qiáng)IntroductionAdvisor使用
作者:FastCoder
在不修改業(yè)務(wù)代碼的情況下如何讓某個(gè)類具有某項(xiàng)功能呢,比如具有XXXDAO接口的能力?IntroductionAdvisor只能應(yīng)用于Introduction類型的通知,而PointcutAdvisor可以應(yīng)用于所有類型的通知
環(huán)境:Spring5.2.14
在不修改業(yè)務(wù)代碼的情況下如何讓某個(gè)類具有某項(xiàng)功能呢,比如具有XXXDAO接口的能力?
1 IntroductionAdvisor介紹
IntroductionAdvisor與PointcutAdvisor區(qū)別
- IntroductionAdvisor只能應(yīng)用于類級(jí)別
- IntroductionAdvisor只能應(yīng)用于Introduction類型的通知,而PointcutAdvisor可以應(yīng)用于所有類型的通知
- IntroductionAdvisor的Advice需要實(shí)現(xiàn)目標(biāo)的接口,而pintcutAdvisor中的Advice沒有改要求
2 IntroductionAdvisor使用流程
假定我們的業(yè)務(wù)類CustomDAO希望具有DesignDAO(接口)的能力
2.1 目標(biāo)接口
- public interface DesignDAO {
- public void design() ;
- }
2.2 Introduction攔截器
- public class CustomIntroductionInterceptor implements IntroductionInterceptor, DesignDAO {
- // 判斷當(dāng)前的攔截器是否實(shí)現(xiàn)了目標(biāo)接口(DesignDAO,我們需要某個(gè)類具有指定接口的功能)
- @Override
- public boolean implementsInterface(Class<?> intf) {
- return intf.isAssignableFrom(this.getClass()) ;
- }
- @Override
- public Object invoke(MethodInvocation invocation) throws Throwable {
- System.out.println("我是通知類:IntroductionInterceptor") ;
- // 判斷當(dāng)前執(zhí)行的方法所屬類是否實(shí)現(xiàn)了目標(biāo)接口
- // 這里必須要進(jìn)行相應(yīng)的判斷攔截,否則會(huì)在沒有被攔截的類方法執(zhí)行的時(shí)候報(bào)錯(cuò)我
- // 因?yàn)槟愕钠渌愃鶎?duì)應(yīng)的接口并沒有在該攔截器中被實(shí)現(xiàn)。
- if (implementsInterface(invocation.getMethod().getDeclaringClass())) {
- return invocation.getMethod().invoke(this, invocation.getArguments()) ;
- }
- return invocation.proceed() ;
- }
- @Override
- public void design() {
- System.out.println("接口實(shí)現(xiàn)了") ;
- }
- }
2.3 IntroductionAdvisor定義
- @Component
- public class CustomIntroductionAdvisor implements IntroductionAdvisor {
- // 定義Advice通知
- @Override
- public Advice getAdvice() {
- return new CustomIntroductionInterceptor() ;
- }
- // 該方法沒有被使用,建議直接返回true
- @Override
- public boolean isPerInstance() {
- return true ;
- }
- // 定義了所要實(shí)現(xiàn)的所有接口
- @Override
- public Class<?>[] getInterfaces() {
- return new Class<?>[] {DesignDAO.class} ;
- }
- // 過濾類,返回true就會(huì)被匹配
- @Override
- public ClassFilter getClassFilter() {
- return new ClassFilter() {
- @Override
- public boolean matches(Class<?> clazz) {
- return CustomDAO.class.isAssignableFrom(clazz) ;
- }
- } ;
- }
- // 在這里我們可以校驗(yàn)我們的Advice類是否實(shí)現(xiàn)了執(zhí)行的接口getInterfaces中定義的接口
- @Override
- public void validateInterfaces() throws IllegalArgumentException {
- // 這里可以參考DefaultIntroductionAdvisor的實(shí)現(xiàn)
- }
- }
這里可以查看示例文檔37示例源碼是如何執(zhí)行的
2.4 驗(yàn)證
- @Component
- public class CustomerDAOImpl implements CustomDAO {
- public void update() {
- System.out.println("更新數(shù)據(jù)..." + this.getClass()) ;
- }
- public void save() {
- System.out.println("保存方法..." + this.getClass()) ;
- }
- }
業(yè)務(wù)類并沒有實(shí)現(xiàn)DesignDAO接口。接下來看看通過上面定義IntroductionAdvisor是否可以讓我們的業(yè)務(wù)類具有目標(biāo)類的功能
- 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() ;
- }
- }
執(zhí)行結(jié)果:
- 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
- 我被調(diào)用了...
- 保存方法...class com.pack.dao.CustomerDAOImpl
- 我是通知類:IntroductionInterceptor, interface com.pack.dao.CustomDAO
- intf: interface com.pack.dao.CustomDAO
- 更新數(shù)據(jù)...class com.pack.dao.CustomerDAOImpl
- IntroductionAdvisor start...
- 我是通知類:IntroductionInterceptor, interface com.pack.interfaces.DesignDAO
- intf: interface com.pack.interfaces.DesignDAO
- 接口實(shí)現(xiàn)了
- IntroductionAdvisor end...
責(zé)任編輯:姜華
來源:
今日頭條