SpringAop源码(四)- EnableAspectJAutoProxy实现原理(下)- createProxy

目录

一、buildAdvisors

二、proxyFactory.getProxy

1、createAopProxy

1)、DefaultAopProxyFactory

2)、AopProxy

2、getProxy

三、createProxy总结:

四、Aop总结:


先梳理一下,上一步拿到的都是Advisor的子类Bean,或者InstantiationModelAwarePointcutAdvisorImpl或者DeclareParentsAdvisor类型的增强。作为当前的Object[] specificInterceptors 调用创建代理方法,最后添加到缓存中。

继续创建代理部分 createProxy:

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
                             @Nullable Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    return proxyFactory.getProxy(getProxyClassLoader());
}

使用ProxyFactory工厂对象为其注入了很多属性,最后调用工厂的getProxy方法获取代理对象。那么分析一下每个步骤:

copyFrom

proxyFactory.copyFrom(this);
public void copyFrom(ProxyConfig other) {
    Assert.notNull(other, "Other ProxyConfig object must not be null");
    this.proxyTargetClass = other.proxyTargetClass;
    this.optimize = other.optimize;
    this.exposeProxy = other.exposeProxy;
    this.frozen = other.frozen;
    this.opaque = other.opaque;
}

重点是this,当前指向AnnotationAwareAspectJAutoProxyCreator,之前分析过其就是一个ProxyConfig的子类,则把一大堆属性进行赋值,后面创建jdk代理还是cglib代理判断使用。

setTargetSource

    当前的TargetSource是外层new SingletonTargetSource外层传入的。

最主要的方法是 addAdvisors(advisors) 和 proxyFactory.getProxy(getProxyClassLoader());

一、buildAdvisors

Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);

protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
    // Handle prototypes correctly...
    Advisor[] commonInterceptors = resolveInterceptorNames();

    List<Object> allInterceptors = new ArrayList<>();
    if (specificInterceptors != null) {
        allInterceptors.addAll(Arrays.asList(specificInterceptors));
        if (commonInterceptors.length > 0) {
            if (this.applyCommonInterceptorsFirst) {
                allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
            }
            else {
                allInterceptors.addAll(Arrays.asList(commonInterceptors));
            }
        }
    }
    if (logger.isTraceEnabled()) {
        int nrOfCommonInterceptors = commonInterceptors.length;
        int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
        logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
                " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
    }

    Advisor[] advisors = new Advisor[allInterceptors.size()];
    for (int i = 0; i < allInterceptors.size(); i++) {
        advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
    }
    return advisors;
}

根据上面拿到的增强数组,调用 this.advisorAdapterRegistry.wrap(allInterceptors.get(i))方法,我们没有设置过该对象,获取到的是默认的

private AdvisorAdapterRegistry advisorAdapterRegistry = 
    GlobalAdvisorAdapterRegistry.getInstance();
private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();

那么就是调用 DefaultAdvisorAdapterRegistry的wrap方法:

public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry {

    private final List<AdvisorAdapter> adapters = new ArrayList<>(3);


	/**
	 * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
	 */
    public DefaultAdvisorAdapterRegistry() {
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }
}

其无参构造默认初始化了三个默认的适配器。

public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
    if (adviceObject instanceof Advisor) {
        return (Advisor) adviceObject;
    }
    if (!(adviceObject instanceof Advice)) {
        throw new UnknownAdviceTypeException(adviceObject);
    }
    Advice advice = (Advice) adviceObject;
    if (advice instanceof MethodInterceptor) {
        // So well-known it doesn't even need an adapter.
        return new DefaultPointcutAdvisor(advice);
    }
    for (AdvisorAdapter adapter : this.adapters) {
        // Check that it is supported.
        if (adapter.supportsAdvice(advice)) {
            return new DefaultPointcutAdvisor(advice);
        }
    }
    throw new UnknownAdviceTypeException(advice);
}

如果是基于@Aspect切面传入的为已经Advisor(切面)类型,所以会直接返回。

但是,其他情况(不知道什么时候会进入,后续分析)

如果还不是则会初始化为DefaultPointcutAdvisor(默认切面类型),结构如下:

二、proxyFactory.getProxy

public Object getProxy(@Nullable ClassLoader classLoader) {
    return createAopProxy().getProxy(classLoader);
}

    分为两步,一个是createAopProxy,一个是getProxy

1、createAopProxy

protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        activate();
    }
    return getAopProxyFactory().createAopProxy(this);
}

首先是一个开关,(在父类中会有监听列表,不知道什么时候用,后面分析)。然后是获取代理工厂,创建代理。我们在new ProxyFactory的时候,父类ProxyCreatorSupport的构造中就初始化了简单工厂DefaultAopProxyFactory 类型的AopProxyFactory。ProxyFactory的结构层级如下:

1)、DefaultAopProxyFactory

public ProxyCreatorSupport() {
    this.aopProxyFactory = new DefaultAopProxyFactory();
}
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class<?> targetClass = config.getTargetClass();
			if (targetClass == null) {
				throw new AopConfigException("TargetSource cannot determine target class: " +
						"Either an interface or a target is required for proxy creation.");
			}
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

	private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
		Class<?>[] ifcs = config.getProxiedInterfaces();
		return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
	}

}
  1. DefaultAopProxyFactory的createAopProxy方法也就是Spring的自动代理。不论EnableAspectJAutoProxy类型启动Aop还是后面分析基于标签方式启动,只要不指定proxyTargetClass为true(默认为false),都会使用Jdk的动态代理;exposeProxy是否暴露动态代理的对象(同一个类或者说Spring Bean中,调用内部的对象,比如A方法调用B方法不会进行切面)。
  2. 只要不指定默认会使用cglib代理,否则使用jdk动态代理;Spring之前的版本要求cglib进行动态代理时,没有无参构造或者构造为private类型,之前可能会报错,现在可以使用Objenesis进行实现。
  3. 当然比如我现在写的基于@Asject的切面,我的UserService没有实现接口,所以还是会在 targetClass.isInterface()判断后使用cglib。

下面还是先看看AopProxy的层次结构

2)、AopProxy

public interface AopProxy {

    Object getProxy();

    Object getProxy(@Nullable ClassLoader classLoader);
}

接口非常简单就两个接口,一个是知道类加载器去获取代理实例,一个是没有指定类加载器获取。

  • 1、JdkDynamicAopProxy
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
	private final AdvisedSupport advised;
	
	public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
		Assert.notNull(config, "AdvisedSupport must not be null");
		if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
			throw new AopConfigException("No advisors and no TargetSource specified");
		}
		this.advised = config;
	}
	
	@Override
	public Object getProxy() {
		return getProxy(ClassUtils.getDefaultClassLoader());
	}

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}
	
	@Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object oldProxy = null;
		boolean setProxyContext = false;

		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
				return equals(args[0]);
			}
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				// The target does not implement the hashCode() method itself.
				return hashCode();
			}
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				// There is only getDecoratedClass() declared -> dispatch to proxy config.
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				// Service invocations on ProxyConfig with the proxy config...
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;

			if (this.advised.exposeProxy) {
				// Make invocation available if necessary.
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			// Get as late as possible to minimize the time we "own" the target,
			// in case it comes from a pool.
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// Get the interception chain for this method.
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			// Check whether we have any advice. If we don't, we can fallback on direct
			// reflective invocation of the target, and avoid creating a MethodInvocation.
			if (chain.isEmpty()) {
				// We can skip creating a MethodInvocation: just invoke the target directly
				// Note that the final invoker must be an InvokerInterceptor so we know it does
				// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// We need to create a method invocation...
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// Proceed to the joinpoint through the interceptor chain.
				retVal = invocation.proceed();
			}

			// Massage return value if necessary.
			Class<?> returnType = method.getReturnType();
			if (retVal != null && retVal == target &&
					returnType != Object.class && returnType.isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
				// Special case: it returned "this" and the return type of the method
				// is type-compatible. Note that we can't help if the target sets
				// a reference to itself in another returned object.
				retVal = proxy;
			}
			else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
				throw new AopInvocationException(
						"Null return value from advice does not match primitive return type for: " + method);
			}
			return retVal;
		}
		finally {
			if (target != null && !targetSource.isStatic()) {
				// Must have come from TargetSource.
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}

}

    jdk代理实现了ProxyFactory的两个接口,还有invoke方法,并且在构造中传入了AdvisedSupport是Advised的一个子类。我们自己写动态代理时候传入的是被代理对象,被封装在AdvisedSupport的TargetSource的getTarget()中,没有传入类加载器的工厂使用默认的类加载器。

  • 2、ObjenesisCglibAopProxy和CglibAopProxy

    ObjenesisCglibAopProxy集成自CglibAopProxy,其中只定义了createProxyClassAndInstance方法,只有在cglibAopProxy的getProxy方法进行调用。那么结构都很清晰了。

 

2、getProxy

 

上一步分析了,由于不同的情况获取到的可能是JdkDynamicAopProxy或者ObjenesisCglibAopProxy。所以实现也会不同:

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isTraceEnabled()) {
        logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
    }
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

之前分析过,Aop基于动态代理实现,可以参见:代理模式-静态代理、JDK和Cglib动态代理,那么Proxy.newProxyInstance就比较熟悉了。

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isTraceEnabled()) {
        logger.trace("Creating CGLIB proxy: " + 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 (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
            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);
        enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(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);
    }
}

protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
    enhancer.setInterceptDuringConstruction(false);
    enhancer.setCallbacks(callbacks);
    return (this.constructorArgs != null && this.constructorArgTypes != null ?
            enhancer.create(this.constructorArgTypes, this.constructorArgs) :
            enhancer.create());
}

cglib的动态代理做了很多判断处理等,但看到Enhancer就比较熟悉了。

三、createProxy总结:

使用ProxyFactory创建代理,而真正创建代理的部分委托给了DefaultAopProxyFactory,根据不同的加载环境判断使用jdk还是cglib动态代理。而创建之前由于传入的可能是切点不是切面,那么会将传入的切点封装成DefaultPointcutAdvisor切面。

 

四、Aop总结:

1、@EnableAspectJAutoProxy注解import了Bean:AspectJAutoProxyRegistrar

2、AspectJAutoProxyRegistrar注入了AnnotationAwareAspectJAutoProxyCreator的BeanDefinition

3、AnnotationAwareAspectJAutoProxyCreator的setBeanFactory初始化了内部对象后续使用

4、AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization(每个Bean的生命周期都会回调)回调方法中,调用wrapIfNecessary方法

5、wrapIfNecessary方法

    1)、getAdvicesAndAdvisorsForBean 将BeanFactory中所有canApply的切面Bean进行返回

    2)、createProxy使用ProxyFactory创建代理,创建代理委派给AopPxoxyFactory根据不同的启动配置参数和情况,判断使用jdk还是cglib动态代理。其中 buildAdvisors是重要方法,如果当前传入的不是切面则使用 DefaultAdvisorAdapterRegistry初始化当前的切点为 DefaultPointcutAdvisor类型的切面。

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值