创建AOP之创建

在前面的文章分析了获取增强器以及匹配的增强器之后,我们便可以根据增强器来创建代理了.

	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);
		// 决定对于给定的bean是否应该使用targetClass而不是他的接口代理
		// 检查proxyTargetClass设置以及preserveTargetClass属性
		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				// 给proxyFactory添加代理接口
				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());
	}

1、增强器的封装

	protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
		// 解析注册的所有 interceptorName
		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++) {
			// 拦截器进行封装转化为Advisor
			advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
		}
		return advisors;
	}
    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
    	// 如果要封装的类型本身就是Advisor类型的,不需要再进行处理
        if (adviceObject instanceof Advisor) {
            return (Advisor)adviceObject;
        } else if (!(adviceObject instanceof Advice)) {
        	// 因为封装方法只对Advisor和Advice两种类型的数据有效,如果不是将不能封装
            throw new UnknownAdviceTypeException(adviceObject);
        } else {
            Advice advice = (Advice)adviceObject;
            if (advice instanceof MethodInterceptor) {
            	// 如果是MethodInterceptor类型,则使用DefaultPointcutAdvisor封装
                return new DefaultPointcutAdvisor(advice);
            } else {
            	// 如果存在Advisor的是配置,同样需要进行封装
                Iterator var3 = this.adapters.iterator();

                AdvisorAdapter adapter;
                do {
                    if (!var3.hasNext()) {
                        throw new UnknownAdviceTypeException(advice);
                    }

                    adapter = (AdvisorAdapter)var3.next();
                } while(!adapter.supportsAdvice(advice));

                return new DefaultPointcutAdvisor(advice);
            }
        }
    }

2、代理的创建和获取

  • 代理的创建
	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		// 创建代理
		return getAopProxyFactory().createAopProxy(this);
	}
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    	// 根据这三个条件来判断使用哪种代理
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            return new JdkDynamicAopProxy(config);
        } else {
            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.");
            } else {
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }

从上面的if条件来看,有3个方面影响着Spring的判断

  1. isOptimize
    用来控制通过CGLIB创建的代理是否使用激进的优化策略.除非完全了解AOP代理如何处理优化,否则不推荐用户使用这个设置.目前这个属性仅仅用于CGLIB代理,对于JDK代理无效.
  2. proxyTargetClass
    这个属性为true的时候,目标类本身被代理而不是目标类的接口,所以为true的时候使用的是CGLIB,配置之前讲到过:<aop:aspectj-autoproxy proxy-target-class=“true”/>
  3. hasNoUserSuppliedProxyInterfaces
    是否存在接口.

1、如果目标对象实现了接口,默认情况下使用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现接口哦,必须采用CGLIB库,Spring会自动在JDK动态代理和CGLIB之间转换

  • 代理的获取

    上面也有分析有两种代理方式:JDK和CGLIB来实现AOP.就分别来分析一下这两种代理的获取

    JDKProxy

    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);
        this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }
    

    我们知道JDKProxy的使用的关键是创建自定义的InvocationHandler,而InvocationHandler中包含了需要覆盖的getProxy,当前的这个方法就是完成这个操作.
    并且确定了JdkDynamicAopProxy实现了InvocationHandler接口,我们就可以推测出JdkDynamicAopProxy中一定有一个invoke函数:

    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;
    
        Boolean var8;
        try {
        	// equals方法和hashCode方法的处理
            if (this.equalsDefined || !AopUtils.isEqualsMethod(method)) {
                if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                    Integer var18 = this.hashCode();
                    return var18;
                }
    			
                if (method.getDeclaringClass() == DecoratingProxy.class) {
                    Class var17 = AopProxyUtils.ultimateTargetClass(this.advised);
                    return var17;
                }
    
                Object retVal;
                if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                    retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
                    return retVal;
                }
    			// 有时候目标对象内部的自我调用无法实现切面中的增强则需要通过此属性暴露代理
                if (this.advised.exposeProxy) {
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }
    
                target = targetSource.getTarget();
                Class<?> targetClass = target != null ? target.getClass() : null;
                // 获取当前方法的拦截器链
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                if (chain.isEmpty()) {
                	// 如果没有发现任何拦截器那么直接调用切点方法
                    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                    retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
                } else {
                	// 将拦截器封装在ReflectiveMethodInvocation
                	// 以便于使用proceed进行连接调用拦截器
                    MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                    // 执行拦截器链
                    retVal = invocation.proceed();
                }
    
                Class<?> returnType = method.getReturnType();
                if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                    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);
                }
    
                Object var12 = retVal;
                return var12;
            }
    
            var8 = this.equals(args[0]);
        } finally {
            if (target != null && !targetSource.isStatic()) {
                targetSource.releaseTarget(target);
            }
    
            if (setProxyContext) {
                AopContext.setCurrentProxy(oldProxy);
            }
    
        }
    
        return var8;
    }
    

    上面的函数中最主要的工作就是创建一个拦截器链,并使用RelfectiveMethodInvocation类进行了链的封装.在ReflectiveMethodInvocation类中的proceed方法中实现了拦截器的逐一调用.继续看一下这个方法

       public Object proceed() throws Throwable {
       // 执行完所有增强后执行切点方法
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return this.invokeJoinpoint();
        } else {
             // 获取下一个要执行的拦截器
            Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
            if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            	// 动态匹配
                InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
                Class<?> targetClass = this.targetClass != null ? this.targetClass : this.method.getDeclaringClass();
                // 如果没有匹配上,则不执行拦截器
                return dm.methodMatcher.matches(this.method, targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
            } else {
            	// 普通拦截器,直接调用拦截器
            	// 将this作为参数传递以保证当前实例中调用链的执行
                return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
            }
        }
    }
    

    在proceed方法中,ReflectiveMethodInvocation中的主要职责就是维护了链接调用的计数器,记录着当前调用链接的位置,以便可以有序的进行下去,这个方法中并没有之前设想的维护各种增强的顺序,而是将此工作委托给了各个增强器,使各个增强器在内部进行逻辑实现.

    CGLIBProxy

    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;
            int x;
            if (ClassUtils.isCglibProxyClass(rootClass)) {
                proxySuperClass = rootClass.getSuperclass();
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                Class[] var5 = additionalInterfaces;
                int var6 = additionalInterfaces.length;
    
                for(x = 0; x < var6; ++x) {
                    Class<?> additionalInterface = var5[x];
                    this.advised.addInterface(additionalInterface);
                }
            }
    		// 验证Class
            this.validateClassIfNecessary(proxySuperClass, classLoader);
            // 创建及配置EnHancer
            Enhancer enhancer = this.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 CglibAopProxy.ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
            // 设置拦截器
            Callback[] callbacks = this.getCallbacks(rootClass);
            Class<?>[] types = new Class[callbacks.length];
    
            for(x = 0; x < types.length; ++x) {
                types[x] = callbacks[x].getClass();
            }
    
            enhancer.setCallbackFilter(new CglibAopProxy.ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
            enhancer.setCallbackTypes(types);
            // 生成代理类以及创建代理
            return this.createProxyClassAndInstance(enhancer, callbacks);
        } catch (IllegalArgumentException | CodeGenerationException var9) {
            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", var9);
        } catch (Throwable var10) {
            throw new AopConfigException("Unexpected AOP exception", var10);
        }
    }
    

    上面的函数描述了创建Spring中的Enhancer的过程,最重要的就是通过getCallbacks方法设置拦截器链.

    private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
    	// 对expose-proxy属性的处理
        boolean exposeProxy = this.advised.isExposeProxy();
        boolean isFrozen = this.advised.isFrozen();
        boolean isStatic = this.advised.getTargetSource().isStatic();
        // 将拦截器封装在DynamicAdvisedInterceptor中
        Callback aopInterceptor = new CglibAopProxy.DynamicAdvisedInterceptor(this.advised);
        Object targetInterceptor;
        if (exposeProxy) {
            targetInterceptor = isStatic ? new CglibAopProxy.StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : new CglibAopProxy.DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
        } else {
            targetInterceptor = isStatic ? new CglibAopProxy.StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : new CglibAopProxy.DynamicUnadvisedInterceptor(this.advised.getTargetSource());
        }
    
        Callback targetDispatcher = isStatic ? new CglibAopProxy.StaticDispatcher(this.advised.getTargetSource().getTarget()) : new CglibAopProxy.SerializableNoOp();
        Callback[] mainCallbacks = new Callback[]{
       		 // 将拦截器链加入Callback中
        	aopInterceptor, 
        	(Callback)targetInterceptor, new CglibAopProxy.SerializableNoOp(), (Callback)targetDispatcher, this.advisedDispatcher, new CglibAopProxy.EqualsInterceptor(this.advised), new CglibAopProxy.HashCodeInterceptor(this.advised)};
        Callback[] callbacks;
        if (isStatic && isFrozen) {
            Method[] methods = rootClass.getMethods();
            Callback[] fixedCallbacks = new Callback[methods.length];
            this.fixedInterceptorMap = new HashMap(methods.length);
    
            for(int x = 0; x < methods.length; ++x) {
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
                fixedCallbacks[x] = new CglibAopProxy.FixedChainStaticTargetInterceptor(chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
                this.fixedInterceptorMap.put(methods[x].toString(), x);
            }
    
            callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
            System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
            System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
            this.fixedInterceptorOffset = mainCallbacks.length;
        } else {
            callbacks = mainCallbacks;
        }
    
        return callbacks;
    }
    

    在这个方法中,Spring考虑了很多情况,但是对于我们来说,只需要理解最常用的就可以了,比如将advised属性封装在DynamicAdvisedInterceptor并加入在callbacks中.
    为什么要这么做呢?CGLIB中对一方法的拦截是通过将自定义的拦截器即实现了MethodInterceptor接口加入Callback中并在调用代理时直接激活拦截器中的intercept方法来实现的.
    DynamicAdvisedInterceptor继承自MethodInterceptor,加入到Callback中后,再次调用代理时会直接调用DynamicAdvisedInterceptor中的intercept方法.
    所以CGLIB方式实现的代理,其核心逻辑必然在DynamicAdvisedInterceptor中的intercept方法.

    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            Object oldProxy = null;
            boolean setProxyContext = false;
            Object target = null;
            TargetSource targetSource = this.advised.getTargetSource();
    
            Object var16;
            try {
                if (this.advised.exposeProxy) {
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }
    
                target = targetSource.getTarget();
                Class<?> targetClass = target != null ? target.getClass() : null;
                // 获取拦截器链
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                Object retVal;
                if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                	// 如果 拦截器为空,则直接激活原方法
                    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                    retVal = methodProxy.invoke(target, argsToUse);
                } else {
                	// 进入链
                    retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();
                }
    
                retVal = CglibAopProxy.processReturnType(proxy, target, method, retVal);
                var16 = retVal;
            } finally {
                if (target != null && !targetSource.isStatic()) {
                    targetSource.releaseTarget(target);
                }
    
                if (setProxyContext) {
                    AopContext.setCurrentProxy(oldProxy);
                }
    
            }
    
            return var16;
        }
    

    上面的方法,其实和JDK方式实现代理中的invoke方法很像,都是先构造链,然后封装此链进行串联调用.只是JDK中使用的ReflectiveMethodInvocation,而在CGLIB中使用的是CglibMethodInvocation.
    CglibMethodInvocation继承自ReflectiveMethodInvocation,但是没有重写proceed方法.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值