3.AOP中的IntroductionAdvisor

上篇中的自定义Advisor是实现的AbstractPointcutAdvisor,Advisor其实还有一个接口级别的IntroductionAdvisor

                   

这个好像用的很少,网上搜了一些资料,说是基于Class的增强,接口的功能扩展,在原有的功能上增加一些其他接口定义的方法,可以将当前代理对象向上转型,然后调用接口中的方法

这个功能暂时还不知道适用于什么场景

示例:

//定义一个some类,只有doSome方法
@Component
public class Some {
    public void doSome() {
        System.out.println("do some...");
    };
}

 

//定义一个other接口,提供doOther功能
public interface IOther {
    public void doOther();
}

  

//定义一个通知器
@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;
    }
}

 

//定义一个通知,要实现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)

@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); } }

 

posted on 2019-08-12 01:52  Hleaves  阅读(1837)  评论(0编辑  收藏  举报