代理创建
Spring AOP 实现主要依赖于 AbstractAutoProxyCreator
类的执行,该类会在 Bean 的创建过程中判断是否需要生成代理对象,并获取 BeanFactory 中的可应用到当前 Bean 的增强通知 Advice。当目标对象 Bean 方法执行时通过动态代理执行时则会执行对应的增强通知方法,最终实现 AOP 切面增强的能力。
下面是 AbstractAutoProxyCreator
创建过程
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
...
//通过ProxyFactory创建目标对象
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
...
// 构建增强通知
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 的创建代理对象过程
public Object getProxy(@Nullable ClassLoader classLoader) {
// 生成 AopProxy 实例,创建代理对象
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// 获取代理创建工厂类并根据代理配置创建 AopProxy 实例
// 默认采用 DefaultAopProxyFactory 类
return getAopProxyFactory().createAopProxy(this);
}
Spring AOP 支持 JDK 动态代理 与 CGLIB 动态代理两种方式,提供了 JdkDynamicAopProxy 与 ObjenesisCglibAopProxy 两种 AOP 动态代理实现类。JDK 仅支持接口的动态代理,而 CGLIB 支持目标类的代理模式,Spring 默认采用了 JDK 动态代理方式。
查看下 DefaultAopProxyFactory
创建 AopProxy
过程
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 优先使用 JDK动态代理
if (!NativeDetector.inNativeImage() &&
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
Class<?> targetClass = config.getTargetClass();
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
JdkDynamicAopProxy
是 Spring AOP 用于创建基于 JDK 动态代理的 AOP 代理对象的核心类。它实现了 AopProxy 与 InvocationHandler 接口,并使用 Java 的 InvocationHandler 来拦截方法调用,最终完成切面增强逻辑。
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
...
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
...
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
...
}
}
java 动态代理通过两个核心类实现:
- 1.
Proxy
类提供了创建代理对象的方法。 - 2.
InvocationHandler
接口定义了代理对象在方法调用时的行为,必须实现该接口并重写 invoke 方法。
在代理对象执行时会执行 InvocationHandler
实现类的 invoke 方法,在 invoke 方法中可以添加自定义逻辑,实现动态增强逻辑。
AOP 执行
JdkDynamicAopProxy
通过 getProxy 获取目标实例 Bean 动态代理对象,在代理对象执行时则会调用 invoke
方法,并在该方法逻辑中实现增强逻辑。下面为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 或者 hashCode 方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
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) {
// 暴露代理对象,将当前代理对象放置到 ThreadLocal 中
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 针对不同类型的 TargetSoruce 获取目标对象
// 比如 SingletonTargetSource 获取单例目标对象,也是最常见类型
// ThreadLocalTargetSource 获取 ThreadLocal 中的目标对象
// CommonsPool2TargetSource 支持从对象池中获取目标对象
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 构建通知增强拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 不存在拦截器则直接执行
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 创建执行上下文对象
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 通过执行
retVal = invocation.proceed();
}
// 方法返回
Class<?> returnType = method.getReturnType();
...
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// 释放目标对象,比如PoolTargetSource 池化类型需要进行释放
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// 恢复旧代理对象
AopContext.setCurrentProxy(oldProxy);
}
}
}
源码解释:
- 判断方法是否为 equals 或 hashCode 等特殊类型方法,以决定是否直接调用目标对象的方法
- 判断配置是否可以代理暴露,然后将其设置到 ThreadLocal 线程变量中
- 通过指定
EnableAspectJAutoProxy(exposeProxy=true)
注解,在程序中通过AopContext.currentProxy()
方法即可获取当前线程变量中的代理对象
- 通过指定
- 通过 TargetSource 实例获取目标对象
- TargetSource 主要作用提供代理对象使用的目标对象,并在允许在代理过程中动态切换目标,比如
CommonsPool2TargetSource
可以从对象池获取目标对象,ThreadLocalTargetSource
可以通过 ThreadLocal 获取目标对象
- TargetSource 主要作用提供代理对象使用的目标对象,并在允许在代理过程中动态切换目标,比如
- 构建应用于目标方法拦截器链,比如前置通知、环绕通知、后置通知方法拦截器
- 构建执行上下文对象
ReflectiveMethodInvocation
并调用proceed
方法,递归执行拦截器逻辑 - 完成代理增强返回结果
ReflectiveMethodInvocation
ReflectiveMethodInvocation
表示目标方法的执行上下文,比如目标实例、方法与方法参数和方法拦截器链,用于目标方法的调用并执行增强拦截器。
proceed
方法源码如下
public Object proceed() throws Throwable {
// 当拦截器链执行到最后时调用目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 获取下一个拦截器并增加拦截器索引
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 判断是动态拦截器还是普通拦截器
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// interceptorOrInterceptionAdvice 可实现参数匹配动态拦截匹配
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
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 {
// 动态匹配失败直接跳过
return proceed();
}
}
else {
// 执行方法拦截器
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
protected Object invokeJoinpoint() throws Throwable {
return AopUtils.invokeJoinpointUsingReflection(target, method, arguments);
}
该方法核心逻辑即递归调用拦截器链中的下一个拦截器,每个方法拦截器在执行时都需要回调ReflectiveMethodInvocation
的 proceed 方法完成链式调用,直到所有拦截器都执行完毕或到达目标方法。