Spring AOP 源码分析 - 创建代理对象
1.简介
我分析了 Spring 是如何为目标 bean 筛选合适的通知器的。现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 bean 的某些方法前后。与筛选合适的通知器相比,创建代理对象的过程则要简单不少,本文所分析的源码不过100行,相对比较简单。
2.创建代理
大家都知道,SpringAOP创建代理类使用了两种技术:jdk的动态代理和cglib,下边我们分别进行分析。
// 创建代理 Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass());
2.1 jdk动态代理
基于 JDK 的动态代理主要是通过 JDK 提供的代理创建类 Proxy 为目标对象创建代理,下面我们来看一下 Proxy 中创建代理的方法声明。如下:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
简单说一下上面的参数列表:
- loader - 类加载器
- interfaces - 目标类所实现的接口列表
- h - 用于封装代理逻辑
JDK 动态代理对目标类是有一定要求的,即要求目标类必须实现了接口,JDK 动态代理只能为实现了接口的目标类生成代理对象。至于 InvocationHandler,是一个接口类型,定义了一个 invoke 方法。使用者需要实现该方法,并在其中封装代理逻辑。
关于 JDK 动态代理的介绍,就先说到这。下面我来演示一下 JDK 动态代理的使用方式,如下:
目标类定义:
public interface UserService { void save(User user); void update(User user); } public class UserServiceImpl implements UserService { @Override public void save(User user) { System.out.println("save user info"); } @Override public void update(User user) { System.out.println("update user info"); } }
代理创建者定义:
public interface ProxyCreator { Object getProxy(); } public class JdkProxyCreator implements ProxyCreator, InvocationHandler { private Object target; public JdkProxyCreator(Object target) { assert target != null; Class<?>[] interfaces = target.getClass().getInterfaces(); if (interfaces.length == 0) { throw new IllegalArgumentException("target class don`t implement any interface"); } this.target = target; } @Override public Object getProxy() { Class<?> clazz = target.getClass(); // 生成代理对象 return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(System.currentTimeMillis() + " - " + method.getName() + " method start"); // 调用目标方法 Object retVal = method.invoke(target, args); System.out.println(System.currentTimeMillis() + " - " + method.getName() + " method over"); return retVal; } }
如上,invoke 方法中的代理逻辑主要用于记录目标方法的调用时间,和结束时间。下面写点测试代码简单验证一下,如下:
public class JdkProxyCreatorTest { @Test public void getProxy() throws Exception { ProxyCreator proxyCreator = new JdkProxyCreator(new UserServiceImpl()); UserService userService = (UserService) proxyCreator.getProxy(); System.out.println("proxy type = " + userService.getClass()); System.out.println(); userService.save(null); System.out.println(); userService.update(null); } }
测试结果如下:

如上,从测试结果中。我们可以看出,我们的代理逻辑正常执行了。另外,注意一下 userService 指向对象的类型,并非是 xyz.coolblog.proxy.UserServiceImpl,而是 com.sun.proxy.$Proxy4。
关于 JDK 动态代理,这里先说这么多。下一节,我来演示一下 CGLIB 动态代理,继续往下看吧。
2.2 CGLIB动态代理
当我们要为未实现接口的类生成代理时,就无法使用 JDK 动态代理了。那么此类的目标对象生成代理时应该怎么办呢?当然是使用 CGLIB 了。在 CGLIB 中,代理逻辑是封装在 MethodInterceptor 实现类中的,代理对象则是通过 Enhancer 类的 create 方法进行创建。下面我来演示一下 CGLIB 创建代理对象的过程,如下:
创建业务类:
package com.wzq.demo02; /** * 业务类 * * 没有实现接口 * * 如果类是final的,则无法生成代理对象,报错 * * 如果方法是final的,代理无效 * * @author Muscleape * */ public class UserServiceImpl { public void addUser() { System.out.println("增加一个用户。。。"); } public void editUser() { System.out.println("编辑一个用户。。。"); } }
cglib代理类,需要实现接口MethodInterceptor
import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class UserServiceCglib implements MethodInterceptor { private Object target; public Object getInstance(Object target) { this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); // 设置回调方法 enhancer.setCallback(this); // 创建代理对象 return enhancer.create(); } /** * 实现MethodInterceptor接口中重写的方法 * * 回调方法 */ @Override public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("事务开始。。。"); Object result = proxy.invokeSuper(object, args); System.out.println("事务结束。。。"); return result; } }
测试类
package com.wzq.demo02; public class TestCglib { public static void main(String[] args) { UserServiceCglib cglib = new UserServiceCglib(); UserServiceImpl bookFacedImpl = (UserServiceImpl) cglib.getInstance(new UserServiceImpl()); bookFacedImpl.addUser(); } }
测试结果
事务开始。。。
增加一个用户。。。
事务结束。。。
3.源码解析
为目标 bean 创建代理对象前,需要先创建 AopProxy 对象,然后再调用该对象的 getProxy 方法创建实际的代理类。我们先来看看 AopProxy 这个接口的定义,如下:
public interface AopProxy { /** 创建代理对象 */ Object getProxy(); Object getProxy(ClassLoader classLoader); }
在 Spring 中,有两个类实现了 AopProxy,如下

Spring 在为目标 bean 创建代理的过程中,要根据 bean 是否实现接口,以及一些其他配置来决定使用 AopProxy 何种实现类为目标 bean 创建代理对象。下面我们就来看一下代理创建的过程,如下:
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); /* * 默认配置下,或用户显式配置 proxy-target-class = "false" 时, * 这里的 proxyFactory.isProxyTargetClass() 也为 false */ if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { /* * 检测 beanClass 是否实现了接口,若未实现,则将 * proxyFactory 的成员变量 proxyTargetClass 设为 true */ evaluateProxyInterfaces(beanClass, proxyFactory); } } // specificInterceptors 中若包含有 Advice,此处将 Advice 转为 Advisor 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()); } public Object getProxy(ClassLoader classLoader) { // 先创建 AopProxy 实现类对象,然后再调用 getProxy 为目标 bean 创建代理对象 return createAopProxy().getProxy(classLoader); }
getProxy 这里有两个方法调用,一个是调用 createAopProxy 创建 AopProxy 实现类对象,然后再调用 AopProxy 实现类对象中的 getProxy 创建代理对象。这里我们先来看一下创建 AopProxy 实现类对象的过程,如下:
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); } public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { /* * 下面的三个条件简单分析一下: * * 条件1:config.isOptimize() - 是否需要优化,这个属性没怎么用过, * 细节我不是很清楚 * 条件2:config.isProxyTargetClass() - 检测 proxyTargetClass 的值, * 前面的代码会设置这个值 * 条件3:hasNoUserSuppliedProxyInterfaces(config) * - 目标 bean 是否实现了接口 */ 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); } // 创建 CGLIB 代理,ObjenesisCglibAopProxy 继承自 CglibAopProxy return new ObjenesisCglibAopProxy(config); } else { // 创建 JDK 动态代理 return new JdkDynamicAopProxy(config); } } }
如上,DefaultAopProxyFactory 根据一些条件决定生成什么类型的 AopProxy 实现类对象。生成好 AopProxy 实现类对象后,下面就要为目标 bean 创建代理对象了。这里以 JdkDynamicAopProxy 为例,我们来看一下,该类的 getProxy 方法的逻辑是怎样的。如下:
public Object getProxy() { return getProxy(ClassUtils.getDefaultClassLoader()); } 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); // 调用 newProxyInstance 创建代理对象 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
如上,请把目光移至最后一行有效代码上,会发现 JdkDynamicAopProxy 最终调用 Proxy.newProxyInstance 方法创建代理对象。到此,创建代理对象的整个过程也就分析完了,不知大家看懂了没。好了,关于创建代理的源码分析,就先说到这里吧。

浙公网安备 33010602011771号