Spring Boot 在初始化过程中,会利用 BeanPostProcessor 后置处理器来创建 AOP 代理。其中,AnnotationAwareAspectJAutoProxyCreator 是关键的后置处理器,它会在 Bean 初始化前后进行处理,判断是否需要为 Bean 创建代理。
- 自动配置引入 AOP 相关组件
Spring Boot 通过自动配置机制引入 AOP 相关组件。在 spring-boot-autoconfigure 模块中,有 AopAutoConfiguration 类,它会根据条件判断是否启用 AOP 自动配置。
不配置默认是开启的
- AnnotationAwareAspectJAutoProxyCreator 后置处理
AnnotationAwareAspectJAutoProxyCreator 继承自 AbstractAutoProxyCreator,而 AbstractAutoProxyCreator 实现了 BeanPostProcessor 接口。在 Bean 初始化完成后(createBean会调用initializeBean,调用postProcessAfterInitialization),postProcessAfterInitialization 方法会被调用,该方法会判断是否需要为 Bean 创建代理。
@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;
}
wrapIfNecessary 方法是创建代理的核心方法,其源码如下:
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;
}
在 wrapIfNecessary 方法中:
首先会进行一些过滤判断,如判断 Bean 是否为基础设施类、是否需要跳过等。
然后调用 getAdvicesAndAdvisorsForBean 方法获取适用于该 Bean 的增强(Advice)和切面(Advisor)。
如果存在适用于该 Bean 的增强和切面,则调用 createProxy 方法创建代理。
- 创建代理对象
在DefaultAopProxyFactory的 createProxy 方法中:
首先创建一个 ProxyFactory 对象,用于配置代理的相关信息。
根据配置决定使用 JDK 动态代理还是 CGLIB 代理(通过 setProxyTargetClass 方法)。只有是接口类或代理类,lamda才走JDK
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
将获取到的增强和切面添加到 ProxyFactory 中。
最后调用 getProxy 方法创建代理对象并返回。
总结:
Spring Boot 在初始化时,通过自动配置引入 AnnotationAwareAspectJAutoProxyCreator 后置处理器,在 Bean 初始化完成后,该后置处理器会判断是否需要为 Bean 创建代理。如果需要,则通过 ProxyFactory 配置代理信息,并根据配置选择合适的代理方式(JDK 动态代理或 CGLIB 代理)创建代理对象。这样就完成了 AOP 代理的创建过程。
两种代理区别:
JDK 动态代理基于 Java 的 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 实现,它要求目标对象实现接口,生成的代理对象也实现相同的接口。代理对象重写的是接口中定义的方法,所以只有接口里定义的方法调用才会经过 InvocationHandler 的 invoke 方法,从而实现 AOP 增强。非接口的方法无法被JDK代理
JDK代理样例:
// 定义接口
interface MyInterface {
void interfaceMethod();
}
// 实现接口的类
class MyClass implements MyInterface {
@Override
public void interfaceMethod() {
System.out.println("Executing interface method.");
}
public void nonInterfaceMethod() {
System.out.println("Executing non-interface method.");
}
}
// 实现 InvocationHandler 接口
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method execution");
Object result = method.invoke(target, args);
System.out.println("After method execution");
return result;
}
}
// 测试代码
import java.lang.reflect.Proxy;
public class JdkProxyTest {
public static void main(String[] args) {
MyClass target = new MyClass();
MyInvocationHandler handler = new MyInvocationHandler(target);
MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
handler
);
// 调用接口方法,会被代理
proxy.interfaceMethod();
// 下面这行代码会编译错误,因为代理对象只能调用接口中定义的方法
// proxy.nonInterfaceMethod();
}
}
CGLIB(Code Generation Library)代理是通过继承目标类来实现的,它会在运行时生成目标类的子类,并重写目标类的方法,从而实现 AOP 增强。因此,只要目标类不是 final 类,其所有方法(包括接口方法和非接口方法)都可以被代理。
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
// 定义类
class MyClass {
public void interfaceMethod() {
System.out.println("Executing interface method.");
}
public void nonInterfaceMethod() {
System.out.println("Executing non-interface method.");
}
}
// 实现 MethodInterceptor 接口
class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method execution");
Object result = proxy.invokeSuper(obj, args);
System.out.println("After method execution");
return result;
}
}
// 测试代码
public class CglibProxyTest {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MyClass.class);
enhancer.setCallback(new MyMethodInterceptor());
MyClass proxy = (MyClass) enhancer.create();
// 调用接口方法,会被代理
proxy.interfaceMethod();
// 调用非接口方法,也会被代理
proxy.nonInterfaceMethod();
}
}