Spring代理创建和代理实现

文章目录

  • 1. 初始化代理工厂:ProxyFactory
  • 2. 实现代理
    • 2.1 选择代理方式(cglib、jdk)
    • 2.2 实现代理的两种方式
      • 3.1 JdkDynamicAopProxy
        • 4.1 getProxy
        • 4.2 invoke
          • 5.1 获取拦截器链
          • 5.2 拦截器链处理
      • 3.2 CglibAopProxy
        • 4.1 创建Enhancer并设置属性
        • 4.2 获取拦截器链

前提:实现代理之前,已经拿到类、方法对应的拦截器数组:specificInterceptors.
因为Spring AOP和Spring 事务的实现都是基于代理的.所以把这个部分抽取出来,以供参考.

1. 初始化代理工厂:ProxyFactory

protected Object createProxy(
        Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
        //..................略
        //代理工厂
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(this);
        //判断是否targetClass代理不是接口代理
        if (!proxyFactory.isProxyTargetClass()) {
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            } else {
                //如果是接口代理,需要添加接口属性
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }
        //适配器模式把拿到的拦截器统一封装成Advisor
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		for (Advisor advisor : advisors) {
			proxyFactory.addAdvisor(advisor);
		}
		//创建代理
		return proxyFactory.getProxy(getProxyClassLoader());
        //...................略
    }

        拦截器封装为Advisor的适配处理看这边:

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

getProxy方法主要包含两个步骤:

  • 获取代理初始化处理类:AopProxy
  • 生成代理
	public Object getProxy(ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}

2. 实现代理

2.1 选择代理方式(cglib、jdk)

        创建代理的方法createProxy会根据配置以及是否继承接口分别生成Jdk或者Cglib代理

protected Object createProxy(
        Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
		//.......................略
        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }
        //生成代理类返回
        return proxyFactory.getProxy(getProxyClassLoader());
    }
    public Object getProxy(ClassLoader classLoader) {
        /**
         * @see JdkDynamicAopProxy#getProxy(ClassLoader)  
         * @see CglibAopProxy#getProxy 
         */
        return createAopProxy().getProxy(classLoader);
    }
    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        /**
         * 满足强制使用CGLIB配置、目标类不是接口、不存在代理接口
         * 使用CGLIB方式进行代理
         * 否则使用JDK动态代理
         * 这边是创建不同AopProxy返回,回去看具体的调用逻辑
         */
        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);
        }
    }

2.2 实现代理的两种方式

3.1 JdkDynamicAopProxy

        JDK代理主要引用于接口代理,他必须继承InvocationHandler接口,实现getProxyInvoke方法

4.1 getProxy

        常规写法:getProxy

    /**
     * 可以看到JDK的动态代理是接口的代理,需要继承InvocationHandler类,并实现invoke方法,这边是proxy的写法。
     * 具体看一下invoke方法
     * @see #invoke(Object, Method, Object[])
     */
    @Override
    public Object getProxy(ClassLoader classLoader) {

        if (logger.isDebugEnabled()) {
            logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
        }
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

4.2 invoke

这边的invoke方法主要分成这几步:

  • equals、hash、method所属类是接口的处理
  • 目标对象内部的自我调用无法实施切面增强,通过此参数暴露代理
  • 拦截器链的处理(空、非空)-- 根据类和方法名
  • 结果返回
 @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //...........略
        try {
            /**
             * equals、hash、method所属类是接口的处理
             */
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
               //...................略
            }

            //目标对象内部的自我调用无法实施切面增强,通过此参数暴露代理
            if (this.advised.exposeProxy) {
                // Make invocation available if necessary.
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }
            //.....................略

            /**
             * 获取当前方法的拦截器链
             * 这边可以看到这个其实是从初始化的Map>中去拿到的.
             */
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            
            if (chain.isEmpty()) {
                /**
                 * 如果没有拦截器链,直接调用method.invoke方法实现
                 */
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                /**
                 * 把过滤器链放进来初始化一个invocation,并调用这个invocation
                 * @see ReflectiveMethodInvocation#proceed()
                 */
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // Proceed to the joinpoint through the interceptor chain.
                retVal = invocation.proceed();
            }

            //返回结果
            Class<?> returnType = method.getReturnType();
            //.............略
            return retVal;
        }
        finally {
           //....................略
        }
    }
5.1 获取拦截器链

这边可以看到,获取拦截器链的方式是

  • 通过缓存获取
    • 缓存存在
      • 返回数组
    • 缓存不存在
      • 通过MethodMatcher查找匹配的拦截器,具体情况具体分析,基本是通过解析注解的方式查找
	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
		MethodCacheKey cacheKey = new MethodCacheKey(method);
		List<Object> cached = this.methodCache.get(cacheKey);
		if (cached == null) {
			cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
					this, method, targetClass);
			this.methodCache.put(cacheKey, cached);
		}
		return cached;
	}
@Override
	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, Class<?> targetClass) {

		// This is somewhat tricky... We have to process introductions first,
		// but we need to preserve order in the ultimate list.
		List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

		for (Advisor advisor : config.getAdvisors()) {
			if (advisor instanceof PointcutAdvisor) {
				// Add it conditionally.
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
					MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
						if (mm.isRuntime()) {
							// Creating a new object instance in the getInterceptors() method
							// isn't a problem as we normally cache created chains.
							for (MethodInterceptor interceptor : interceptors) {
								interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
							}
						}
						else {
							interceptorList.addAll(Arrays.asList(interceptors));
						}
					}
				}
			}
			else if (advisor instanceof IntroductionAdvisor) {
				IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
				if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
					Interceptor[] interceptors = registry.getInterceptors(advisor);
					interceptorList.addAll(Arrays.asList(interceptors));
				}
			}
			else {
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}

		return interceptorList;
	}
5.2 拦截器链处理

        如果拦截器链不为空,会一直去执行完所有匹配的拦截器链(method的invoke调用)

    @Override
    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);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            /**
             * 如果是一个拦截器的匹配对象,则动态匹配拦截器和匹配到的拦截器进行执行
             */
            InterceptorAndDynamicMethodMatcher dm =
                (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            }
            else {
                /**
                 * 下一次匹配
                 */
                return proceed();
            }
        }
        else {
            /**
             * 普通拦截器直接调用invoke
             */
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

3.2 CglibAopProxy

        cglib需要通过Enhancer类来使用,所以这边的操作其实也是构建这样的类,来实现具体操作

4.1 创建Enhancer并设置属性

    @Override
    public Object getProxy(ClassLoader classLoader) {
      	
        try {
            //.................略

            //创建Enhancer并设置属性,这个是CGLB调用的具体实现--设置属性
            Enhancer enhancer = createEnhancer();
            //.......设置属性,略

            //拦截器的获取和设置
            Callback[] callbacks = getCallbacks(rootClass);
            //.......................略

            // Enhancer创建
            return createProxyClassAndInstance(enhancer, callbacks);
        }
        catch (CodeGenerationException ex) {
          // ..................略
        }
    }

4.2 获取拦截器链

        这边主要看一下拦截器链包装的处理 DynamicAdvisedInterceptor继承自Methodlnterceptor.这个接口是Spring支持的,实现他的intercept方法可以实现代理的目的

    private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
        //............略
        /**
         * 66.拦截器的包装,DynamicAdvisedInterceptor继承自Methodlnterceptor,会实现他的intercept方法来实现CGLB调用
         * @see DynamicAdvisedInterceptor#intercept(Object, Method, Object[], MethodProxy)
         */
        Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
 		//............略
        //将拦截器添加到Callback数组中
        Callback[] mainCallbacks = new Callback[] {aopInterceptor, targetInterceptor, new SerializableNoOp(),  targetDispatcher, this.advisedDispatcher, new EqualsInterceptor(this.advised),new HashCodeInterceptor(this.advised)};
		//.......................略
        return callbacks;
    }

        也就是说这里返回的callback回调数组其实是DynamicAdvisedInterceptor的实现.把callback数组设置到Enhancer中帮助实现调用
        DynamicAdvisedInterceptor实现了MethodInterceptor接口,并实现了intercept方法.可以看到,这里的itercept的实现和JDK代理是一样的

		@Override
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Class<?> targetClass = null;
			Object target = null;
			try {
				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 = getTarget();
				if (target != null) {
					targetClass = target.getClass();
				}
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
				// Check whether we only have one InvokerInterceptor: that is,
				// no real advice, but just reflective invocation of the target.
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
					// 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 = methodProxy.invoke(target, argsToUse);
				}
				else {
					// We need to create a method invocation...
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
				retVal = processReturnType(proxy, target, method, retVal);
				return retVal;
			}
			finally {
				if (target != null) {
					releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}

你可能感兴趣的:(#,Java源码分析,#,Spring源码分析,源码阅读)