Spring AOP(面向切面编程)是Spring框架的核心模块之一,它通过提供另一种编程方式来补充Spring的IoC容器,使得开发者能够模块化横切关注点(如日志、事务、安全等)。本文将深入剖析Spring AOP的底层实现原理,从基本概念到动态代理机制,再到源码级别的实现细节。
AOP(Aspect Oriented Programming)即面向切面编程,是一种对某一类事情的集中处理的编程范式。与OOP(面向对象编程)不同,AOP关注的是横切关注点(cross-cutting concerns),这些关注点通常散布在应用程序的多个地方,但与核心业务逻辑无关。
Spring AOP中几个核心概念:
Spring AOP与AspectJ是两种不同的AOP实现:
Spring AOP借用了AspectJ的一些注解(如@Aspect、@Before等),但其底层实现是基于动态代理而非AspectJ的编译器或织入器。
Spring AOP的实现原理基于动态代理和字节码操作。整体流程可分为三个阶段:
Spring AOP采用的是运行时织入,具体发生在Bean初始化完成后,通过BeanPostProcessor对Bean进行包装。主要步骤包括:
Spring AOP底层使用两种动态代理技术:
适用条件:目标类实现了至少一个接口。
实现原理:
java.lang.reflect.Proxy
类创建代理对象InvocationHandler
的invoke
方法关键代码示例:
javapublic class JdkDynamicAopProxy implements AopProxy, InvocationHandler {
private final AdvisedSupport advised;
@Override
public Object getProxy() {
return Proxy.newProxyInstance(
getClass().getClassLoader(),
advised.getTargetSource().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInterceptor methodInterceptor = advised.getMethodInterceptor();
MethodInvocation methodInvocation = new ReflectiveMethodInvocation(
advised.getTargetSource().getTarget(),
method,
args,
methodInterceptor,
advised.getTargetSource().getTargetClass()
);
return methodInvocation.proceed();
}
}
适用条件:目标类没有实现任何接口。
实现原理:
MethodInterceptor
的intercept
方法关键代码示例:
javapublic class CglibAopProxy implements AopProxy {
private final AdvisedSupport advised;
@Override
public Object getProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(advised.getTargetSource().getTargetClass());
enhancer.setCallback(new DynamicAdvisedInterceptor(advised));
return enhancer.create();
}
}
对比维度 | JDK动态代理 | CGLIB代理 |
---|---|---|
实现方式 | 基于接口 | 基于类继承 |
性能 | 创建速度快,调用稍慢 | 创建速度慢,调用快 |
依赖 | 目标类必须实现接口 | 目标类不能是final |
方法拦截 | 只能拦截接口方法 | 可以拦截所有非final方法 |
默认使用 | Spring AOP 1.x默认 | Spring AOP 2.x+默认 |
Spring AOP的核心处理流程主要涉及以下几个关键类:
在Spring容器启动阶段,会解析所有带有@Aspect注解的类,并将其转换为Advisor对象缓存起来:
当Bean初始化完成后,AbstractAutoProxyCreator(AnnotationAwareAspectJAutoProxyCreator的父类)会执行以下逻辑:
javaprotected 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;
}
// 获取适用于该bean的advisor
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;
}
javapublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
当代理对象的方法被调用时,会触发通知链的执行,这是通过责任链+递归的模式实现的。核心类是ReflectiveMethodInvocation:
关键代码逻辑:
javapublic class ReflectiveMethodInvocation implements ProxyMethodInvocation {
protected final Object target;
protected final Method method;
protected Object[] arguments;
private final List<Object> interceptorsAndDynamicMethodMatchers;
private int currentInterceptorIndex = -1;
public Object proceed() throws Throwable {
// 如果拦截器执行完毕,则调用目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 递归调用下一个拦截器
return ((MethodInterceptor) interceptorOrInterceptionAdvice)
.invoke(this);
}
}
虽然Spring AOP非常强大,但在使用时需要注意:
代理选择:
切点表达式优化:
通知类型选择:
避免自调用问题:
Spring AOP作为Spring框架的核心功能之一,其底层实现基于动态代理技术,通过精巧的设计实现了对横切关注点的模块化管理。理解其原理对于高效使用Spring AOP至关重要:
通过深入理解这些原理,开发者可以更好地利用Spring AOP构建高内聚、低耦合的企业级应用,同时也能在遇到问题时更快地定位和解决。