spring中的ProxyFactory

目录

从spring-aop讲起

AbstractAutoProxyCreator

wrapIfNecessary()

引出ProxyFactory

ProxyFactory如何使用

定义一个接口

定义一个实现

接口实现类默认走Jdk Proxy

再加一个impl类,这个类不实现接口

非接口实现类走cglib:

强制走cglib

源码分析:

JdkDynamicAopProxy

调用链

ReflectiveMethodInvocation


从spring-aop讲起

了解spring-aop的同学应该都知道,aop的关键处理类是AbstractAutoProxyCreator,这个类实现了SmartInstantiationAwareBeanPostProcessor接口,SmartInstantiationAwareBeanPostProcessor接口继承了InstantiationAwareBeanPostProcessor接口,InstantiationAwareBeanPostProcessor接口继承了BeanPostProcessor,BeanPostProcessor中定义了关键的方法postProcessAfterInitialization。而AbstractAutoProxyCreator就是实现了这个关键方法。

AbstractAutoProxyCreator

/**
	 * Create a proxy with the configured interceptors if the bean is
	 * identified as one to proxy by the subclass.
	 * @see #getAdvicesAndAdvisorsForBean
	 */
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

这里只是简单的找一下ProxyFacotry的位置,对于spring-aop本身不做过多介绍。这里可以看到关键方法就是这个wrapIfNecessary,意为按需进行aop包装。

wrapIfNecessary()

/**
	 * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
	 * @param bean the raw bean instance
	 * @param beanName the name of the bean
	 * @param cacheKey the cache key for metadata access
	 * @return a proxy wrapping the bean, or the raw bean instance as-is
	 */
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

其中getAdvicesAndAdvisorsForBean()就是获取advice、advisor的地方,比如用户定义的@Aspect切面,或Advisor的bean等,获取到拦截器后,创建代理对象proxy。

引出ProxyFactory

/**
	 * Create an AOP proxy for the given bean.
	 * @param beanClass the class of the bean
	 * @param beanName the name of the bean
	 * @param specificInterceptors the set of interceptors that is
	 * specific to this bean (may be empty, but not null)
	 * @param targetSource the TargetSource for the proxy,
	 * already pre-configured to access the bean
	 * @return the AOP proxy for the bean
	 * @see #buildAdvisors
	 */
	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对象,proxyFactory.addAdvisors(advisors);添加切面,proxyFactory.getProxy()获取代理后的对象。可以说ProxyFactory是spring-aop较为底层的类,一般来说在应用中添加AOP也不是通过这种方式,而是使用切点、切面等。

下面正式进入ProxyFactory部分。

ProxyFactory如何使用

定义一个接口

public interface HelloService {
    String sayHello(String params);
}

定义一个实现

@Service
public class HelloServiceImpl implements HelloService {

    @Override
    public String sayHello(String params) {
        return "from hessian:"+params;
    }
}

接口实现类默认走Jdk Proxy

        ProxyFactory pf = new ProxyFactory();
		pf.setTarget(new HelloServiceImpl());
    	pf.setInterfaces(HelloService.class);
        // 添加切面,在方法执行前打印一句话
        // 注意这里是 org.aopalliance.intercept.MethodInterceptor;
    	pf.addAdvice(new MethodInterceptor() {
			@Override
			public Object invoke(MethodInvocation invocation) throws Throwable {
				System.out.println("进来了");
				return invocation.proceed();
			}
		});
        // 获取代理后的对象
    	HelloService proxy = (HelloService) pf.getProxy();
    	System.out.println(proxy.getClass());
    	String sayHello = proxy.sayHello("111");
    	System.out.println(sayHello);

运行后打印:
class com.sun.proxy.$Proxy0
进来了
from hessian:111

切面成功加上了,代理后的类是个java Proxy。这是ProxyFactory的默认代理模式。

再加一个impl类,这个类不实现接口

@Service
public class HelloService0Impl {

    public String sayHello(String params) {
        return "from hessian:"+params;
    }
}

非接口实现类走cglib:

        ProxyFactory pf = new ProxyFactory();
		pf.setTarget(new HelloService0Impl());
        // 没有实现接口,默认就是cglib,不需要显式设置
    	// pf.setProxyTargetClass(true);
    	pf.addAdvice(new MethodInterceptor() {
			@Override
			public Object invoke(MethodInvocation invocation) throws Throwable {
				System.out.println("进来了");
				return invocation.proceed();
			}
		});
    	HelloService0Impl proxy = (HelloService0Impl) pf.getProxy();
    	System.out.println(proxy.getClass());
    	String sayHello = proxy.sayHello("111");
    	System.out.println(sayHello);
运行结果:
class demo.proxyfactory.HelloService0Impl$$EnhancerBySpringCGLIB$$70d3a6a1
进来了
from hessian:111

切面加上了,走的是cglib生成的proxy代理类。

强制走cglib

再编写一个,实现接口的类,但强制走cglib:

        ProxyFactory pf = new ProxyFactory();
		pf.setTarget(new HelloServiceImpl());
    	pf.setInterfaces(HelloService.class);
        // 强制走cglib
    	pf.setProxyTargetClass(true);
    	pf.addAdvice(new MethodInterceptor() {
			@Override
			public Object invoke(MethodInvocation invocation) throws Throwable {
				System.out.println("进来了");
				return invocation.proceed();
			}
		});
    	HelloService proxy = (HelloService) pf.getProxy();
    	System.out.println(proxy.getClass());
    	String sayHello = proxy.sayHello("111");
    	System.out.println(sayHello);
运行结果:
class demo.proxyfactory.HelloServiceImpl$$EnhancerBySpringCGLIB$$fac980c9
进来了
from hessian:111

可以发现虽然实现了接口,但还是走了cglib的代理。

源码分析:

    /**
	 * Create a new proxy according to the settings in this factory.
	 * <p>Can be called repeatedly. Effect will vary if we've added
	 * or removed interfaces. Can add and remove interceptors.
	 * <p>Uses a default class loader: Usually, the thread context class loader
	 * (if necessary for proxy creation).
	 * @return the proxy object
	 */
	public Object getProxy() {
		return createAopProxy().getProxy();
	}

    /**
	 * Subclasses should call this to get a new AOP proxy. They should <b>not</b>
	 * create an AOP proxy with {@code this} as an argument.
	 */
	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
        // AopFactory这里是DefaultAopProxyFactory
		return getAopProxyFactory().createAopProxy(this);
	}

这里在拿到DefaultAopProxyFactory后,进入关键的逻辑了。

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        // 这里明确判断了,如果设置了proxyTargetClass为true,或者没有实现什么接口
		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 proxy了,没法走cglib
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
            // 没强制指定,或实现了接口了,就走jdk proxy
			return new JdkDynamicAopProxy(config);
		}
	}
    // 省略其他函数
}

JdkDynamicAopProxy

这里只看一下JdkDynamicAopProxy:

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

这里有几个重点:

1.他代理的接口是通过AopProxyUtils.completeProxiedInterfaces()获取的列表

2.他自身实现了Jdk Proxy的InvocationHandler接口,所以重点关注他的invoke方法

    @Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		MethodInvocation invocation;
		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...
				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);
			}
		}
	}

这个是重中之重了,理解了这个,再看ObjenesisCglibAopProxy也会容易许多。

1.target = targetSource.getTarget(); 这个获取目标对象。不管是通过proxyFactory.setTarget()还是proxyFactory.setTargetSource(),最终都是设置了一个TargetSource.

2.this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); #最关键处

调用链

这里获取了一个调用链。不用管他是怎么来的,他一定是把我们加的切面给包含了的。

然后创建一个ReflectiveMethodInvocation调用对象,里面有个currentInterceptorIndex从-1开始,他会按顺序调用完这些切面。

ReflectiveMethodInvocation

最后就是ReflectiveMethodInvocation了:

    @Override
	@Nullable
	public Object proceed() throws Throwable {
		//	We start with an index of -1 and increment early.
        // 如果已经到头了,就调用原method真实方法,因为是从-1开始的,切面数至少是1,至少走一次
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}
        // 按索引取拦截器
		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			// Evaluate dynamic method matcher here: static part will already have
			// been evaluated and found to match.
            // 动态匹配的情况,一般较少用到
			InterceptorAndDynamicMethodMatcher dm =
					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
			Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
			if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
                // 调用拦截器,拦截器最后一行是invocation.proceed(),也就是会再次回来.
				return dm.interceptor.invoke(this);
			}
			else {
				// Dynamic matching failed.
				// Skip this interceptor and invoke the next in the chain.
				return proceed();
			}
		}
		else {
			// It's an interceptor, so we just invoke it: The pointcut will have
			// been evaluated statically before this object was constructed.
            // 调用拦截器,拦截器最后一行是invocation.proceed(),也就是会再次回来.
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

本篇到此结束,有问题欢迎一起讨论。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

brimsullowr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值