您现在的位置是:亿华云 > IT科技类资讯
Spring 引介增强IntroductionAdvisor使用
亿华云2025-10-03 18:14:13【IT科技类资讯】6人已围观
简介环境:Spring5.2.14在不修改业务代码的情况下如何让某个类具有某项功能呢,比如具有XXXDAO接口的能力?1 IntroductionAdvisor介绍IntroductionAdvisor与
环境: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...很赞哦!(531)
上一篇: 如何通过仿真提高数据中心性能
下一篇: 2022年主要数据中心可持续发展趋势