3.AOP中的IntroductionAdvisor
上篇中的自定义Advisor是实现的AbstractPointcutAdvisor,Advisor其实还有一个接口级别的IntroductionAdvisor
这个好像用的很少,网上搜了一些资料,说是基于Class的增强,接口的功能扩展,在原有的功能上增加一些其他接口定义的方法,可以将当前代理对象向上转型,然后调用接口中的方法
这个功能暂时还不知道适用于什么场景
示例:
1 2 3 4 5 6 7 | //定义一个some类,只有doSome方法 @Component public class Some { public void doSome() { System.out.println( "do some..." ); }; } |
1 2 3 4 | //定义一个other接口,提供doOther功能 public interface IOther { public void doOther(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //定义一个通知器 @Component public class OtherIntroductionAdvisor extends DefaultIntroductionAdvisor { public OtherIntroductionAdvisor() { super ( new OtherIntroductionInterceptor()); } // createBean的时候判断bean是否需要被代理 @Override public boolean matches(Class<?> clazz) { //只代理some对象 boolean assignableFrom = clazz.isAssignableFrom(Some. class ); return assignableFrom; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | //定义一个通知,要实现IOther接口 public class OtherIntroductionInterceptor implements IntroductionInterceptor, IntroductionInfo, IOther { //实现doOther方法 @Override public void doOther() { System.out.println( "do other ..." ); } //扩展功能的实现 @Override public Object invoke(MethodInvocation invocation) throws Throwable { //当前方法的声明类是否实现了需要拓展功能的接口 if (implementsInterface(invocation.getMethod().getDeclaringClass())) { //调用this的此方法 return invocation.getMethod().invoke( this , invocation.getArguments()); } return invocation.proceed(); } @Override public boolean implementsInterface(Class<?> ifc) { Class<?>[] interfaces = this .getInterfaces(); for (Class clazz : interfaces) { if (ifc.isInterface() && ifc.isAssignableFrom(clazz)) { return true ; } } return false ; } @Override public Class<?>[] getInterfaces() { return new Class[] {IOther. class }; } } |
在创建代理对象时,将拓展功能的接口set进去,所以代理对象上转型才不会报错
org.springframework.aop.framework.CglibAopProxy#getProxy(java.lang.ClassLoader)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | @Override public Object getProxy( @Nullable ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug( "Creating CGLIB proxy: target source is " + this .advised.getTargetSource()); } try { Class<?> rootClass = this .advised.getTargetClass(); Assert.state(rootClass != null , "Target class must be available for creating a CGLIB proxy" ); Class<?> proxySuperClass = rootClass; if (ClassUtils.isCglibProxyClass(rootClass)) { proxySuperClass = rootClass.getSuperclass(); Class<?>[] additionalInterfaces = rootClass.getInterfaces(); for (Class<?> additionalInterface : additionalInterfaces) { this .advised.addInterface(additionalInterface); } } // Validate the class, writing log messages as necessary. validateClassIfNecessary(proxySuperClass, classLoader); // Configure CGLIB Enhancer... Enhancer enhancer = createEnhancer(); if (classLoader != null ) { enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache( false ); } } enhancer.setSuperclass(proxySuperClass); // 获取接口信息并且set到代理对象的接口中 enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces( this .advised)); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setStrategy( new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = new Class<?>[callbacks.length]; for ( int x = 0 ; x < types.length; x++) { types[x] = callbacks[x].getClass(); } // fixedInterceptorMap only populated at this point, after getCallbacks call above enhancer.setCallbackFilter( new ProxyCallbackFilter( this .advised.getConfigurationOnlyCopy(), this .fixedInterceptorMap, this .fixedInterceptorOffset)); enhancer.setCallbackTypes(types); // Generate the proxy class and create a proxy instance. return createProxyClassAndInstance(enhancer, callbacks); } catch (CodeGenerationException | IllegalArgumentException ex) { throw new AopConfigException( "Could not generate CGLIB subclass of " + this .advised.getTargetClass() + ": Common causes of this problem include using a final class or a non-visible class" , ex); } catch (Throwable ex) { // TargetSource.getTarget() failed throw new AopConfigException( "Unexpected AOP exception" , ex); } } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步