所有文章已迁移至csdn,csdn个人主页bugpool.blog.csdn.net
Spring AOP源码目录
Spring AOP源码01:Jdk动态代理底层源码
Spring AOP源码02:ProxyFactory
Spring AOP源码03:JdkDynamicAopProxy
Spring AOP源码04:MethodInvocation 拦截器调用
Spring AOP源码05:DefaultAdvisorAutoProxyCreator
Spring期末考压轴题:当Spring AOP遇上循环依赖
git注释源码地址:https://github.com/chaitou/spring-framework-master.git
前言
本篇将重点剖析ProxyFactory
类的源码,很多人不理解为什么要将大部分精力花在讲解ProxyFactory
上,毕竟没有人会使用这么底层的Spring AOP实现方式?
ProxyFactory实现代理需要手动设置Traget
(目标对象)、Interface
(代理接口)、Advice
(增强),然后调用getProxy
生成代理对象。而使用注解形式的Spring AOP并没有想象中的复杂,不过是寻找所有@Aspect
注解的类以及所有@Before
等增强,再通过@Pointcut
上的匹配条件进行匹配,最后获取到所有匹配的Advice
(增强)进行生成代理。因此,注解形式的AOP并不深奥,只不过是帮我们自动寻找匹配增强
,并在Spring Ioc创建Bean的过程中寻找合适的时机
,调用getProxy生成代理,仅此而已。因此,如果我们将手动硬编码的方式(ProxyFactory
)学透了,基本上也就掌握了Spring AOP了,至于注解的形式,我们只需要再探究一下Advice
如何获取以及匹配就可以了
剖去注解与Xml的配置,Spring AOP的核心就是ProxyFactory
,抓住主线,才能更好的把握源码脉络,不至于被边角的细节所干扰
ProxyFactory
代码示例
我们将会写一个UserService
接口,定义findUser
方法,同时在before跟after使用Advice
(增强)对方法进行增强,最后使用ProxyFactory
进行代理的生成。
在这里有必要先大致介绍一下Advice(增强)和Advisor(切面),2个单词长的有点像,但是他们是聚合的关系。
- 增强(
Advice
):常见的有Before advice
、After returning advice
,也就是在连接点进行扩展操作 - 切点(
Pointcut
):也就是连接点,用于判断当前方法或者类是否需要增强 - 切面(
Advisor
):可以看做的增强
和切点
的结合。假设一个方法需要进行增强,则遍历所有切面,调用Pointcut
进行判断当前切面是否适用,如果适用,则调用当前Advice
进行增强
接口:
public interface UserService {
public void findUser();
}
实现类:
public class UserServiceImpl implements UserService {
@Override
public void findUser() {
System.out.println("findUser...");
}
}
2个增强:
// 前置增强
public class LogBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("before log...");
}
}
// 后置增强
public class LogAfterAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("after log...");
}
}
测试:
public class UserServiceImplImplTest {
@Test
public void findUser() {
// 1. 创建代理工厂
ProxyFactory factory = new ProxyFactory();
// 2. 设置代理目标对象
factory.setTarget(new UserServiceImpl());
// 3. 设置接口
factory.setInterfaces(new Class[]{UserService.class});
// 4. 设置增强
factory.addAdvice(new LogBeforeAdvice());
factory.addAdvice(new LogAfterAdvice());
// 5. 获取代理对象
UserService userService = (UserService) factory.getProxy();
userService.findUser();
}
}
运行结果:
before log...
findUser...
after log...
Process finished with exit code 0
ProxyFactory继承关系
我们重点关心一下类,忽略接口
-
ProxyConfig
:用于保存Proxy的相关基础配置,比如是否使用激进模式optimize、强制开起cglib代理proxyTargetClass、是否暴露代理exposeProxy等,在xml配置中十分常见,例如
强制开启Cglib代理 -
AdvisedSupport
:AOP的配置管理类,比起ProxyConfig,其还保存了targetSource
、切面的集合advisors
、接口集合interfaces
等 -
ProxyCreatorSupport
:代理工厂的基础类,提供对可配置AopProxyFactory
的便捷访问
源码分析
- 创建代理工厂,直接调用默认空构造器
- 设置代理目标对象,将
target
对象封装成TargetSource
对象,为什么要多此一举呢?其实TargetSource
的目的是为了做对象池和多例用的,也就是说每次代理都从池中获取对象。而这里我们只使用SingletonTargetSource
,关于TargetSource
留到后面讲解。刚刚提到这些属性都是保存在AdvisedSupport
中的
public void setTarget(Object target) {
setTargetSource(new SingletonTargetSource(target));
}
@Override
public void setTargetSource(@Nullable TargetSource targetSource) {
this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
}
- 设置接口数组,同样保存到
AdvisedSupport
的属性中
public void setInterfaces(Class>... interfaces) {
Assert.notNull(interfaces, "Interfaces must not be null");
// 先清空再添加
this.interfaces.clear();
for (Class> ifc : interfaces) {
addInterface(ifc);
}
}
public void addInterface(Class> intf) {
Assert.notNull(intf, "Interface must not be null");
// 校验如果不是接口则抛出异常
if (!intf.isInterface()) {
throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
}
if (!this.interfaces.contains(intf)) {
this.interfaces.add(intf);
adviceChanged();
}
}
- 设置
Advice
,前面我们说过Advice
只是增强,因此我们要封装成Advisor
切面才能加到AdvisedSupport
的advisors
集合中。而需要注意的是因为没有配置任何的Pointcut
,因此将使用DefaultPointcutAdvisor
进行创建
@Override
public void addAdvice(Advice advice) throws AopConfigException {
int pos = this.advisors.size();
addAdvice(pos, advice);
}
@Override
public void addAdvice(int pos, Advice advice) throws AopConfigException {
Assert.notNull(advice, "Advice must not be null");
if (advice instanceof IntroductionInfo) {
// We don't need an IntroductionAdvisor for this kind of introduction:
// It's fully self-describing.
// 单独处理引介增强
addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
}
else if (advice instanceof DynamicIntroductionAdvice) {
// We need an IntroductionAdvisor for this kind of introduction.
// DynamicIntroductionAdvice只能作为IntroductionAdvisor的一部分
throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
}
else {
// 普通增强
addAdvisor(pos, new DefaultPointcutAdvisor(advice));
}
}
而DefaultPointcutAdvisor
的意思就是无论什么方法都匹配,因此可以看到Pointcut使用的是Pointcut.TRUE
,无论匹配什么方法都是true
new DefaultPointcutAdvisor(advice)
// Pointcut.TRUE
// 也就是说该Advisor的匹配均为true,匹配任何的方法,不做任何限制!
public DefaultPointcutAdvisor(Advice advice) {
this(Pointcut.TRUE, advice);
}
- 创建代理,这才是本篇的重头戏
public Object getProxy() {
return createAopProxy().getProxy();
}
代码就createAopProxy().getProxy()
一句,在调用getProxy()
之前,我们得弄清楚是什么对象调用的getProxy()
,换句话说,也就是createAopProxy()
到底创建了什么对象
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
----------------------------------------------------------------
public AopProxyFactory getAopProxyFactory() {
// 返回的是类中的成员变量aopProxyFactory
return this.aopProxyFactory;
}
----------------------------------------------------------------
// 成员变量的实例化则是在默认构造器中
private AopProxyFactory aopProxyFactory;
// 构造器,调用了DefaultAopProxyFactory进行实例化,因此aopProxyFactory真正的类型是DefaultAopProxyFactory
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
跟踪发现createAopProxy()
返回的是属性aopProxyFactory
,而属性aopProxyFactory
又是在ProxyCreatorSupport
构造器时进行实例化的,真正的类是DefaultAopProxyFactory
,因此继续跟踪DefaultAopProxyFactory
的createAopProxy
方法
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// isOptimize开启激进模式 || proxyTargetClass=true(强制开启cglib代理) || 接口集合为空
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代理
return new ObjenesisCglibAopProxy(config);
}
else {
// 使用JDK代理
return new JdkDynamicAopProxy(config);
}
}
...
}
可以看到,当config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)
为真时才会使用Cglib代理,而当代理对象有实现接口,并且没有强制开启cglib代理时默认使用的是JDK代理,也就是JdkDynamicAopProxy
类。
也就是说,最后将调用的其实是new JdkDynamicAopProxy(config).getProxy()
,结合Jdk动态代理底层源码的内容,可以预想到有2个需要特别关注的方法。getProxy
和invoke
方法
// JdkDynamicAopProxy.java
@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);
// 判断接口是否又hashCode和equals方法
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 使用JDK代理(classLoader, 接口, 当前JdkDynamicAopProxy对象:用于回调invoke和target对象方法)
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
// 上述代码
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
// 第一篇[Jdk动态代理底层源码]中学习的代码是一模一样的
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
可以看出,其实每个知识点都是关联在一起的,ProxyFactory
作为Spring AOP的核心,使用的也是我们学习过的Jdk动态代理
来实现的。结合第一篇Jdk动态代理底层源码的内容,最最重要的便是getProxy
和invoke
方法,下一节我们将进行JdkDynamicAopProxy
中getProxy
和invoke
方法的源码剖析