Spring——6. AOP介绍及源码实现(二)

10 篇文章 0 订阅
2 篇文章 0 订阅

1. 创建代理

在上文Spring——6. AOP介绍及源码实现(一)的最后已经完成了获取所有对应bean的增强器,在这篇文章中再来继续代理的创建及获取。

AbstractAutoProxyCreator.java

Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

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 {
			evaluateProxyInterfaces(beanClass, proxyFactory);
		}
	}
	// 拦截器封装为增强器(把多种类型的增强器Advisor、拦截器MethodInterceptor、增强方法等封装成统一的 Advisor)
	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
	// 增强器加入到 ProxyFactory中
	proxyFactory.addAdvisors(advisors);
	// 设置要代理的类
	proxyFactory.setTargetSource(targetSource);
	// 定制代理
	customizeProxyFactory(proxyFactory);
	// 控制代理工厂被配置之后,是否允许修改通知,默认不允许 修改代理的配置
	proxyFactory.setFrozen(this.freezeProxy);
	if (advisorsPreFiltered()) {
		proxyFactory.setPreFiltered(true);
	}
	// 获取代理对象
	return proxyFactory.getProxy(getProxyClassLoader());
}

对于代理类的创建及处理,Spring委托给了 ProxyFactory;在当前这个方法中,主要是对ProxyFactory的初始化操作和一些属性的赋值,也就是对真正的创建代理做准备,包括如下内容:

  1. copy当前类中的相关属性;
  2. 设置代理接口;
  3. 设置封装好的Advisor到ProxyFactory中;
  4. 设置要代理的类;
  5. 为子类提供了定制的方法 customizeProxyFactory(),可供子类对 ProxyFactory做进一步的封装;
  6. 获取代理对象(包括创建代理及获取代理);

其中,封装Advisor、创建和获取代理两个步骤最为复杂,继续再对这两个步骤进行探索。

2.1 封装Advisor

protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
	// Handle prototypes correctly...
	// 解析注册的所有的 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));
			}
		}
	}
	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;
}

DefaultAdvisorAdapterRegistry.java

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;
	if (advice instanceof MethodInterceptor) {
		// So well-known it doesn't even need an adapter.
		// 如果是 MethodInterceptor 类型则使用DefaultPointcutAdvisor封装
		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);
}

因为Spring中涉及很多的拦截器、增强器、增强方法等方式来对逻辑进行增强,所以需要统一封装成为 Advisor来进行代理的创建。

所以在这里首先是把传入的specificInterceptors(也就是前面获取并过滤之后的增强器)添加到 allInterceptors中,然后再遍历allInterceptors,对其中的每个adviceObject,统一的封装为 Advisor对象。

2.2 获取代理对象

AbstractAutoProxyCreator.java

return proxyFactory.getProxy(getProxyClassLoader());

ProxyFactory.java

public Object getProxy(@Nullable ClassLoader classLoader) {
	// createAopProxy():获取 AOP代理实例对象 (JdkDynamicAopProxy、ObjenesisCglibAopProxy)
	// getProxy:获取真正的代理对象:
	// JdkDynamicAopProxy:Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);代理对象调用方法时使用:invoke()
	// ObjenesisCglibAopProxy:createProxyClassAndInstance(enhancer, callbacks);代理对象调用方法时使用:intercept()
	return createAopProxy().getProxy(classLoader);
}

2.2.1 创建代理

DefaultAopProxyFactory.java

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	// optimize:控制通过CGLIB(对JDK动态代理无效)创建的代理是否使用激进的优化策略(不推荐用户修改)
	// proxyTargetClass:true时,目标类本身将被代理,而不是目标类的接口,CGLIB代理被创建;
	// 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.");
		}
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}
		return new ObjenesisCglibAopProxy(config);
	} else {
		return new JdkDynamicAopProxy(config);
	}
}

Spring的代理中有两种实现,分别是 JDK动态代理的实现和CGLIB的实现;我们来从上面的源码中看看Spring到底是怎么选择代理方式的。

  • if的条件中有3个方面影响Spring的判断:
    1. optimize:控制通过CGLIB创建的代理是否使用激进的优化策略;(这个属性仅用于CGLIB代理,对于JDK动态代理无效,不推荐用户修改这个设置)
    2. proxyTargetClass:这个属性为true时,目标类本身被代理而不是目标类实现的接口被代理;true时,CGLIB代理将被创建,设置方式为 <aop:aspectj-autoproxy proxy-target-class="true"/>; (这样也可以强制使用CGLIB实现AOP)
    3. hasNoUserSuppliedProxyInterfaces:是否存在代理接口;
  • 在满足if条件之后,还有一个条件 (targetClass.isInterface() || Proxy.isProxyClass(targetClass),即当目标类本身就是一个接口或者代理类时,使用JDK动态代理;否则使用CGLIB代理;
  • 都不满足这3个条件的话,默认使用JDK动态代理;

在上文Spring——6. AOP介绍及源码实现(一)中的 2.2.1.1 小节中的“处理 proxy-target-class以及 expose-proxy属性”小段中讲述了JDK动态搭理和CGLIB代理的区别。

在确定了使用哪种代理方式之后,就可以进行代理的创建了。

2.2.2 获取代理

在分析Spring的AOP代理获取的实现之前,我们先来看看JDK动态代理和CGLIB代理本身的使用方式,然后再和Spring的实现进行比较。

2.2.2.1 JDK动态代理的使用
2.2.2.1.1 使用示例
  1. 创建业务接口,业务对外提供的接口:
public interface UserService {
	void add();
}
  1. 创建业务接口实现类:
public class UserServiceImpl implements UserService {
	public void add() {
		System.out.println("-------add--------");
	}
}
  1. 创建自定义的 InvocationHandler,用于对接口提供的方法进行增强:
public class MyInvocationHandler implements InvocationHandler {
	private Object target;

	public MyInvocationHandler(Object target) {
		this.target = target;
	}

	/**
	 * 执行目标对象的方法
	 */
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("--------------before-------------");
		// 执行方法
		Object result = method.invoke(target, args);
		System.out.println("--------------after-------------");
		return result;
	}

	/**
	 * 获取目标对象的代理对象
	 */
	public Object getProxy() {
		return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), this);
	}
}
  1. 创建测试类:
public class ProxyTest {
	public static void main(String[] args) {
		// 实例化目标对象
		UserService userService = new UserServiceImpl();
		userService.add();
		System.out.println();

		MyInvocationHandler myInvocationHandler = new MyInvocationHandler(userService);

		// 根据目标对象生成代理对象
		UserService proxy = (UserService)myInvocationHandler.getProxy();
		proxy.add();
	}
}

// Output:
-------add--------

--------------before-------------
-------add--------
--------------after--------------

可以看到,直接使用目标对象调用add()方法的时候是没有什么效果的;当使用代理对象调用add()方法的时候,在add()方法执行的前后进行了增强。这其实就是AOP的简单实现了。

总结一下JDK动态代理的使用方式:在整个创建过程中,最为核心的是对于 InvocationHandler的创建,在自定义的InvocationHandler中需要重写 invoke()方法,也是在这个方法中实现了对于目标方法的增强
然后还需要提供一个getProxy()方法,在这个方法中创建代理对象并返回。

2.2.2.1.1 SpringJDK动态代理的实现

我们再来看看Spring中的JDK代理的实现是不是跟我们上面的示例一样,继续上面的源码,看看 JdkDynamicAopProxy 类中的内容。

首先我们看到了 JdkDynamicAopProxy类实现了 InvocationHandler接口,也就是说 JdkDynamicAopProxy就是自定义的 InvocationHandler。

再继续,又看到了 JdkDynamicAopProxy类中也有一个getProxy()方法,这个方法也就是用于获取目标对象的代理对象:

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

同时我们也看到了 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;
	try {
		// equals方法的处理
		if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
			return equals(args[0]);
		}
		// hashCode方法的处理
		else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
			return hashCode();
		} else if (method.getDeclaringClass() == DecoratingProxy.class) {
			return AopProxyUtils.ultimateTargetClass(this.advised);
		}
		// isAssignableFrom(Class cls):
		// 如果调用这个方法的 class或interface 与 参数cls 表示的类或接口相同,或者 是参数cls表示的类或接口 的父类,返回true;
		// ArrayList.class.isAssignableFrom(Object.class) // false
		// Object.class.isAssignableFrom(ArrayList.class) // true
		else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
				method.getDeclaringClass().isAssignableFrom(Advised.class)) {
			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()) {
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			// 如果没有发现任何拦截器,那么直接调用切点方法(反射)
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
		} else {
			// We need to create a method invocation...
			// 将拦截器链封装在 ReflectiveMethodInvocation, 并使用其 proceed() 进行链接调用拦截器
			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())) {
			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()) {
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			// Restore old proxy.
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}

上面的方法中最主要的工作就是获取到了匹配当前切点方法的拦截器链,然后使用 ReflectiveMethodInvocation对拦截器进行封装
然后在 ReflectiveMethodInvocation类是 proceed()方法中实现了拦截器的依次调用。

继续探索 proceed()方法是怎么实现拦截器的依次调用的:

public Object proceed() thrjavaows Throwable {
	// We start with an index of -1 and increment early.
	// 如果执行完了所有增强,才执行切点方法(目标方法)
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}
	// 获取下一个要执行的拦截器(每执行一个拦截器,currentInterceptorIndex+1)
	Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInter
	// 如果是 InterceptorAndDynamicMethodMatcher 类型
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		// Evaluate dynamic method matcher here: static part will already have
		// been evaluated and found to match.
		// 动态匹配
		InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionA
		Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass())
		if (dm.methodMatcher.matches(this.method, 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 {
		// It's an interceptor, so we just invoke it: The pointcut will have
		// been evaluated statically before this object was constructed.
		// 如果是普通拦截器,直接调用拦截器
		/**
		 * 比如:
		 * ExposeInvocationInterceptor
		 * DelegatePerTargetObjectIntroductionInterceptor
		 * MethodBeforeAdviceInterceptor
		 * AspectJAroundAdvice
		 * AspectJAfterAdvice
		 * ...
		 */
		return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
	}
}

上面的代码的实现可以总结为以下几个步骤:

  1. 判断拦截器链中的拦截器是否全部执行完毕,如果都执行了一遍,才执行目标方法;
  2. 获取下一个拦截器,每获取一次,计数器 +1;
  3. 执行拦截器:xxxInterceptor.invoke(this);

也就是说,先执行所有的拦截器,最后才会执行目标方法。

那如果是这样的话,Spring又是怎么实现这种“包裹”式的调用顺序的呢?

before()…
add()…
after()…
afterReturning()…

到了这里,我们就得接上文Spring——6. AOP介绍及源码实现(一)中的“2.2.2.1.1.1 增强器的获取”小节的最后面——不同的增强器(这里的拦截器)里面的执行方法(invoke())了,所以我们来看看不同的拦截器的invoke()方法的实现。

  1. @Before拦截器的实现(MethodBeforeAdviceInterceptor):
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
	private final MethodBeforeAdvice advice;
	public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}
	
	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
		return mi.proceed();
	}

可以看到:

  • 先执行了 this.advice.before() 方法,即执行@Before方法(反射)
  • 再执行了mi.proceed();(这个mi是上面传入的this,也就是 ReflectiveMethodInvocation对象)即递归执行 ReflectiveMethodInvocation中的procceed()方法
  1. @After拦截器的实现(AspectJAfterAdvice):
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable {

	// others
	......

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		}
		finally {
			// 激活增强方法
			invokeAdviceMethod(getJoinPointMatch(), null, null);
		}
	}

	// others
	......
}

可以看到:

  • 先执行了 mi.proceed();同上,递归执行 ReflectiveMethodInvocation中的procceed()方法
  • 再执行了 invokeAdviceMethod(),即执行@After方法
  1. @AfterThrowing拦截器的实现(AspectJAfterThrowingAdvice):
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable {

	// others
	......

    @Override
	public Object invoke(MethodInvocation mi) throws Throwable {
    	try {
    		return mi.proceed();
    	}
    	catch (Throwable ex) {
    		if (shouldInvokeOnThrowing(ex)) {
    			invokeAdviceMethod(getJoinPointMatch(), null, ex);
    		}
    		throw ex;
    	}
    }
	// others
	......
}

可以看到:

  • 先执行了 mi.proceed();同上,递归执行 ReflectiveMethodInvocation中的procceed()方法
  • 在mi.proceed()执行异常的时候,捕捉异常再执行invokeAdviceMethod(),即执行@AfterThrowing方法
  1. @Around拦截器的实现(AspectJAroundAdvice):
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {

	// others
	......

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		if (!(mi instanceof ProxyMethodInvocation)) {
			throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
		}
		ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
		ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
		JoinPointMatch jpm = getJoinPointMatch(pmi);
		return invokeAdviceMethod(pjp, jpm, null, null);
	}

	// others
	......

}

可以看到:

  • @Around拦截器不会去在源码中去执行 mi.proceed()方法,而是直接执行@Around方法
  • 所以我们需要在 @Around方法中去执行 mi.proceed()方法;同时可以在前后分别做增强,比如:
@Around("test()")
public Object aroundTest(ProceedingJoinPoint point) {
	System.out.println("before1");
	Object object = null;
	try {
		object = point.proceed();
	} catch (Throwable t) {
		t.printStackTrace();
	}
	System.out.println("after1");
	return object;
}

看到这里,我们应该就能回答这个问题了;从拦截器的语句执行顺序中,我们看到了:
只有@Before拦截器是先执行 @Before的方法,再执行 mi.proceed()方法;其他的都是先执行 mi.proceed()方法,再执行 @After等方法

所以这样就实现了这个效果:before()在目标方法之前被执行,其余的在目标方法之后被执行。

也就是说,依靠 ReflectiveMethodInvocation的proceed()方法 与 多个不同拦截器之间的递归调用,实现了Spring AOP的拦截器链对于目标方法的不同调用顺序的增强

再画一下AOP递归的责任链:
image.png

2.2.2.2 CGLIB代理的使用

CGLIB是一个强大的高性能的代码生成包。它广泛地被许多AOP的框架使用,例如Spring AOP 和dynaop,为他们提供方法的拦截(Interception)。

CGLIB包的底层通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。除了CGLIB包,脚本语言如 Groovy和 BeanShell,也是使用ASM来生成Java的字节码。

2.2.2.2.1 使用示例
  1. 创建业务实现类(这里就不是接口了)
public class UserService {
	public void add() {
		System.out.println("----------add----------");
	}
}
  1. 创建自定义的 MethodInterceptor,用于对目标方法进行增强:
public class MyMethodInterceptor implements MethodInterceptor {
	private Object target;

	public MyMethodInterceptor(Object target) {
		this.target = target;
	}

	public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
		System.out.println("----before---- invoke " + method);
		Object result = methodProxy.invokeSuper(o, objects);
		System.out.println("----after---- invoke " + method);
		return result;
	}

	public Object getProxy(){
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(target.getClass());
		enhancer.setCallback(this);

		return enhancer.create();
	}
}
  1. 创建测试类:
public class EnHancerTest {
	public static void main(String[] args) {
		UserService userService = new UserService();
		userService.add();
		System.out.println();

		MyMethodInterceptor myMethodInterceptor = new MyMethodInterceptor(userService);
		UserService proxy = (UserService)myMethodInterceptor.getProxy();
		proxy.add();
		System.out.println();
		System.out.println(proxy);
	}
}

// Output:
----------add----------

----before---- invoke public void org.bgy.spring.study.spring.aop.simple.proxy.cglib.UserService.add()
----------add----------
----after---- invoke public void org.bgy.spring.study.spring.aop.simple.proxy.cglib.UserService.add()

----before---- invoke public java.lang.String java.lang.Object.toString()
----before---- invoke public native int java.lang.Object.hashCode()
----after---- invoke public native int java.lang.Object.hashCode()
----after---- invoke public java.lang.String java.lang.Object.toString()
org.bgy.spring.study.spring.aop.simple.proxy.cglib.UserService$$EnhancerByCGLIB$$ab5fc9f7@73c6c3b2

可以看到,跟上面使用JDK动态代理一样,直接使用目标对象调用add()方法的时候是没有什么效果的;当使用代理对象调用add()方法的时候,在add()方法执行的前后进行了增强。

在使用System.out.println(proxy)的时候,调用了toString()方法和 hashCode()方法,也对这两个方法的前后进行了增强;最后生成的对象为 EnhancerByCGLIB$$ab5fc9f7@73c6c3b2 实例,这也就是在运行时由CGLIB生成的代理对象。

使用CGLIB实现动态代理的方式跟JDK动态代理实现很像,最为核心的也是对于MethodInterceptor的创建,然后在自定义 MethodInterceptor中去重写 intercept()方法,在这个方法中实现了对目标方法的增强。
也是还需要提供一个getProxy()方法,在这个方法中创建代理对象并返回。

2.2.2.2.2 CGLIB代理的实现

继续看看Spring源码的CGLIB代理的实现是否跟我们的示例相似,继续上面的源码,看看 ObjenesisCglibAopProxy 类中的内容。

可以看到,ObjenesisCglibAopProxy 类中只是重写了 CglibAopProxy类的一个 createProxyClassAndInstance()方法,所以CGLIB的代理是由 CglibAopProxy类实现的,继续跟进。

果然看到,CglibAopProxy类中也有一个 getProxy()方法:

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.
		// 验证 Class
		validateClassIfNecessary(proxySuperClass, classLoader);
		// Configure CGLIB Enhancer...
		// 创建 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));
		// 设置拦截器链(即 MethodInterceptor)
		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);
	}
}

在这个方法中实现了 Enhancer的创建及使用 enhancer对象创建了目标对象的代理对象并返回

在getCallbacks()方法中Spring考虑了很多种情况,但是对于我们来说,只需要理解最常规的就可以了,即封装了advised属性的DynamicAdvisedInterceptor,并把它加入到callbacks中;那这样做了之后又是怎么实现对于方法的拦截的呢?

前面的示例中,我们可以知道 CGLIB对于方法的拦截是通过将自定义的拦截器(实现了MethodInterceptor)加入到Enhancer的 callbacks中,并在使用代理对象调用方法时,直接激活拦截器中的 interceptor方法来实现的

那我们再来看看 DynamicAdvisedInterceptor类中的内容:

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
	private final AdvisedSupport advised;
	public DynamicAdvisedInterceptor(AdvisedSupport advised) {
		this.advised = advised;
	}
	@Override
	@Nullable
	// 对于CGLIB实现的代理,核心实现逻辑在这里
	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();
		try {
			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);
			// 获取当前方法的拦截器链(这里的chain链没有排序,哪里排序的?)
			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...
				// 拦截器链不为空
				// 将拦截器链封装在 CglibMethodInvocation, 并使用其 proceed() 进行链接调用拦截器
				// (CglibMethodInvocation 继承自ReflectiveMethodInvocation,但没有重写proceed()方法;在JDK代理中直接使用了 ReflectiveMethodInvocation)
				CglibMethodInvocation invocation = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy);
				// 执行拦截器链
				retVal = invocation.proceed();
			}
			retVal = processReturnType(proxy, target, method, retVal);
			return retVal;
		}
		finally {
			if (target != null && !targetSource.isStatic()) {
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}
	@Override
	public boolean equals(@Nullable Object other) {
		return (this == other ||
				(other instanceof DynamicAdvisedInterceptor &&
						this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));
	}
	/**
	 * CGLIB uses this to drive proxy creation.
	 */
	@Override
	public int hashCode() {
		return this.advised.hashCode();
	}
}

在这个类中的 intercept()方法也跟 JdkDynamicAopProxy类中的invoke()方法类似,获取到了匹配当前切点方法的拦截器链,然后封装拦截器链进行调用;不同的就是 在JdkDynamicAopProxy类中使用的是 ReflectiveMethodInvocation进行封装,而在 CglibAopProxy类中使用的是 CglibMethodInvocation进行封装。

而 CglibMethodInvocation继承自 ReflectiveMethodInvocation,并且没有重写 proceed()方法,所以最终 CGLIB中对于拦截器的依次调用的实现就跟 JDK动态代理中对于拦截器的依次调用的实现完全相同,这里就不再重复讲述了。

到这里,已经探索完成了Spring AOP在源码中的实现

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值