美文网首页
6.6Spring的AOP的解析——代理的创建

6.6Spring的AOP的解析——代理的创建

作者: szhlcy | 来源:发表于2019-02-12 11:34 被阅读0次

 获取了对应的增强器之后,就是对需要代理的目标类进行代理的创建了。</br>
 createProxy方法主要是对,ProxyFactory对象进行初始化,为真正的代理的创建做准备。

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

        ProxyFactory proxyFactory = new ProxyFactory();
        // Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
        //从ProxyConfig(创建代理的配置的便捷超类,以确保所有代理创建者具有一致的属性)复制设置的代理属性
        proxyFactory.copyFrom(this);
        //确定给定的bean是否应该使用其目标类而不是其接口进行代理
        // 1.proxyTargetClass属性设置的值a,2.beanName对应的Bean设置的preserveTargetClass
        if (!shouldProxyTargetClass(beanClass, beanName)) {
            // Must allow for introductions; can't just set interfaces to  the target's interfaces only.
            //获取所有的需要代理的类的相关的接口,并加入ProxyFactory的interfaces属性中
            Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
            for (Class<?> targetInterface : targetInterfaces) {
                proxyFactory.addInterface(targetInterface);
            }
        }
        //将给定的拦截器统一封装为Advisor类型的
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        //将代理的增强类挨个加入ProxyFactory的advisors属性中
        for (Advisor advisor : advisors) {
            proxyFactory.addAdvisor(advisor);
        }
        //设置对应的代理目标bean
        proxyFactory.setTargetSource(targetSource);
        //用户自定义的代理
        customizeProxyFactory(proxyFactory);
        //控制代理工厂被设置了之后,是否还允许修改通知,默认为false(即在被配置之后,不允许修改代理的配置)
        proxyFactory.setFrozen(this.freezeProxy);
        //返回子类返回的Advisors是否已预过滤以匹配bean的目标类,允许在构建AOP调用的顾问程序链时跳过ClassFilter检查
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }

        return proxyFactory.getProxy(this.proxyClassLoader);
    }

(1)获取当前设置的代理属性(ProxyConfig类中)

(2)判断是否用目标类进行代理而不是接口进行代理,并添加代理接口

(3)添加Advisor到proxyFactory中

(4)设置需要被代理的类

(5)根据用户是否实现了customizeProxyFactory方法,来看是否进一步对proxyFactory进行处理

(6)进行代理的获取操作

 这里对拦截器的封装进行解析:

    protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) {
        // Handle prototypes correctly...
        //获取并解析所有的interceptorName,一般都是空的
        Advisor[] commonInterceptors = resolveInterceptorNames();

        List<Object> allInterceptors = new ArrayList<Object>();
        if (specificInterceptors != null) {
            //将特定Bean的拦截器集合放到一起
            allInterceptors.addAll(Arrays.asList(specificInterceptors));
            if (commonInterceptors != null) {
                //如果设置了首先应用CommonInterceptors就把commonInterceptors放到拦截器集合最前面,如果不是则按顺序
                if (this.applyCommonInterceptorsFirst) {
                    allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
                }
                else {
                    allInterceptors.addAll(Arrays.asList(commonInterceptors));
                }
            }
        }
        if (logger.isDebugEnabled()) {
            int nrOfCommonInterceptors = (commonInterceptors != null ? commonInterceptors.length : 0);
            int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
            logger.debug("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适配器注册类(默认为GlobalAdvisorAdapterRegistry)来对拦截器进行封装
            advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
        }
        return advisors;
    }

 现在对warp方法进行解析,这个方法的作用是对所有的拦截器进行统一的封装,封装为Advisor。

    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
        //如果需要封装的对象---是---Advisor类型就不需要处理
        if (adviceObject instanceof Advisor) {
            return (Advisor) adviceObject;
        }
        //此方法值对Advisor和Advice类型两种数据进行封装,如果不知就不能封装
        if (!(adviceObject instanceof Advice)) {
            throw new UnknownAdviceTypeException(adviceObject);
        }
        Advice advice = (Advice) adviceObject;
        //如果需要封装的对象---是---MethodInterceptor类型,则使用DefaultPointcutAdvisor不需要适配
        if (advice instanceof MethodInterceptor) {
            // So well-known it doesn't even need an adapter.
            return new DefaultPointcutAdvisor(advice);
        }
        //如果是Advisor的适配器那么也同样需要进行封装
        for (AdvisorAdapter adapter : this.adapters) {
            // Check that it is supported.
            //检查是否是支持适配的类型
            if (adapter.supportsAdvice(advice)) {
                return new DefaultPointcutAdvisor(advice);
            }
        }
        throw new UnknownAdviceTypeException(advice);
    }

 当proxyFactory初始化之后就是进行代理的创建了

    public Object getProxy(ClassLoader classLoader) {
        return createAopProxy().getProxy(classLoader);
    }
    
    protected final synchronized AopProxy createAopProxy() {
        //active这个值的作用是在创建第一个AOP代理时设置为true,并告诉对应的监听器第一个AOP在创建
        if (!this.active) {
            activate();
        }
        //创建代理
        return getAopProxyFactory().createAopProxy(this);
    }   

&esmp;接下来就是进行代理的创建

    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        //在这里判断代理的设置属性,
        //optimize:代理是否应该执行积极的优化,默认为false
        //proxyTargetClass:是否直接代理目标类以及任何接口
        //hasNoUserSuppliedProxyInterfaces: 判断是否又用户提供的代理接口
        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.");
            }
            //如果需要代理的类是接口则使用jdk代理
            if (targetClass.isInterface()) {
                return new JdkDynamicAopProxy(config);
            }
            //使用cglib代理方式
            return CglibProxyFactory.createCglibProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

 从上面看到又三个判断条件,影响spring的代理使用方式:
(1)optimize: 用来控制通过CGLIB创建的代理是否使用激进的优化策略,除非完全了解AOP如何进行优化的,则不应该设置这个值(这个值只对CGLIB代理方法有用)</br>
(2)proxyTargetClass: 这个属性为true时,目标类本身被代理而不是目标类的接口,如果这个属性值被设置为true,则使用CGLIB</br>
(3)hasNoUserSuppliedProxyInterfaces:是否存在用户自定义的代理的接口</br>
 如果目标实现了接口,可以使用JDK代理(默认),也可以强制使用CGLIB方法进行代理的创建,如果目标对象没有实现接口,则必须使用CGLIB库。</br>
 JDK动态代理只能对实现了接口的类生成代理,而不能针对类。</br>
 CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以这个类或方法最好不要声明为final类型的。</br>
 对于JDK的动态代理使用,我们需要自定义一个类实现InvocationHandler,并实现其中需要重写的3个函数:1.构造函数,将代理的对象传入;2.invoke方法,此方法中实现了AOP增强的所有逻辑;3.getProxy方法。同理spring使用JDK的动态代理同样需要用这种方式,因此JdkDynamicAopProxy类实现了InvocationHandler类并且会在invoke方法中把AOP的核心逻辑写在其中。

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MethodInvocation invocation;
        Object oldProxy = null;
        boolean setProxyContext = false;

        TargetSource targetSource = this.advised.targetSource;
        Class<?> targetClass = null;
        Object target = null;

        try {
            //如果没有在代理接口中定义equal方法,并且代理的方法是equals方法
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // The target does not implement the equals(Object) method itself.
                return equals(args[0]);
            }
            //同上是对hashCode方法的处理
            if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                // The target does not implement the hashCode() method itself.
                return hashCode();
            }
            //如果代理方法是接口中的方法并且方法是Advised相同的类或者接口则进行处理
            //Class类的isAssignableFrom(Class cls)表示如果调用这个方法的class或接口 与参数cls表示的类或接口相同,或者是
            //参数cls表示的类或接口的父类,则返回true
            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;
            //如果目标对象存在内部的自我调用,则需要暴露代理
            //exposeProxy: 设置代理是否应该由AOP框架作为ThreadLocal公开,以便通过AopContext类进行检索。如果建议的对象需要自己调用另一个建议的方法,这将非常有用
            if (this.advised.exposeProxy) {
                // Make invocation available if necessary.
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }

            // May be null. Get as late as possible to minimize the time we "own" the target,
            // in case it comes from a pool.
            target = targetSource.getTarget();
            if (target != null) {
                targetClass = target.getClass();
            }

            // 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.
                //如果不存在任何拦截器,则直接进行切点方法的调用
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
            }
            else {
                // We need to create a method invocation...
                //将拦截器链封装在ReflectiveMethodInvocation对象中,以便使用proceed方法调用
                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.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);
            }
        }
    }

 现在对proceed进行解析

    public Object proceed() throws Throwable {
        //  We start with an index of -1 and increment early.
        //检查是否所有的拦截器方法都执行完了,执行完了之后就调用切点方法
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }
        //获取下一个需要执行的拦截器
        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        //如果拦截器是InterceptorAndDynamicMethodMatcher(内部框架类,将MethodInterceptor实例与MethodMatcher组合,用作顾问程序链中的元素)类型的
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // Evaluate dynamic method matcher here: static part will already have been evaluated and found to match.
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            //对对应的方法和目标类以及参数进行匹配,如果匹配上则执行拦截方法,不匹配则不执行,调用下一个拦截器
            if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            }
            else {
                // Dynamic matching failed.
                // Skip this interceptor and invoke the next in the chain.
                return proceed();
            }
        }
        else {
            //如果是普通的拦截器,所以我们只是调用它。普通的拦截器有:ExposeInvocationInterceptor,DelegatingIntroductionInterceptor,MethodBeforeAdviceInterceptor,AspectJAroundAdvice,AspectJAfterThrowingAdvice,AspectJAfterAdvice等
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

相关文章

网友评论

      本文标题:6.6Spring的AOP的解析——代理的创建

      本文链接:https://www.haomeiwen.com/subject/xviheqtx.html