Spring AOP中的设计模式分析
1. 代理模式 (Proxy Pattern)
源码分析:
Spring AOP通过使用JDK动态代理或CGLIB字节码生成来创建代理对象,以实现切面功能。JDK动态代理用于代理实现了接口的类,而CGLIB用于代理没有实现接口的类。以下是相关源码的简要分析:
JDK动态代理:
Spring使用Proxy
类和InvocationHandler
接口来创建代理对象。public class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable { private final AdvisedSupport advised; public JdkDynamicAopProxy(AdvisedSupport config) { this.advised = config; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, advised.getTargetSource().getTarget(), method, args, advised.getInterceptorsAndDynamicInterceptionAdvice(method, advised.getTargetClass())); return invocation.proceed(); } }
- 分析代码片段的功能:
JdkDynamicAopProxy
类实现了InvocationHandler
接口,通过invoke
方法实现代理逻辑。invoke
方法调用ReflectiveMethodInvocation
对象的proceed
方法,该方法会按顺序执行所有拦截器和目标方法。
- 分析代码片段的功能:
CGLIB代理:
Spring使用CGLIB库生成子类来实现代理。public class CglibAopProxy implements AopProxy { private final AdvisedSupport advised; public CglibAopProxy(AdvisedSupport advised) { this.advised = advised; } @Override public Object getProxy(ClassLoader classLoader) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.advised.getTargetSource().getTargetClass()); enhancer.setCallback(new DynamicAdvisedInterceptor(this.advised)); return enhancer.create(); } } private static class DynamicAdvisedInterceptor implements MethodInterceptor { private final AdvisedSupport advised; public DynamicAdvisedInterceptor(AdvisedSupport advised) { this.advised = advised; } @Override public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable { MethodInvocation invocation = new CglibMethodInvocation(target, method, args, proxy, advised.getInterceptorsAndDynamicInterceptionAdvice(method, advised.getTargetClass())); return invocation.proceed(); } }
- 分析代码片段的功能:
CglibAopProxy
类通过CGLIB的Enhancer
创建目标类的子类,并将DynamicAdvisedInterceptor
设置为回调。DynamicAdvisedInterceptor
实现了MethodInterceptor
接口,其intercept
方法会按顺序执行所有拦截器和目标方法。
- 分析代码片段的功能:
设计思想:
代理模式通过代理对象控制对目标对象的访问,可以在目标对象的方法调用前后执行一些额外的操作,而不需要修改目标对象本身的代码。
解决的问题:
- 透明代理:客户端无需知道目标对象是否被代理,只需要使用代理对象即可。
- 灵活扩展:在不改变目标对象的情况下,通过代理对象可以添加额外的功能,如日志记录、事务管理等。
优缺点:
- 优点:
- 透明性:客户端对代理对象的使用与对目标对象的使用一致,增加了透明性。
- 灵活性:可以动态地为目标对象添加功能,增强了代码的灵活性和可扩展性。
- 缺点:
- 性能开销:代理对象的创建和方法调用有一定的性能开销,特别是在使用CGLIB时。
- 复杂性:引入代理模式会增加系统的复杂性,特别是代理链较长时。
2. 装饰模式 (Decorator Pattern)
源码分析:
AOP切面可以看作是在不改变目标对象的情况下,动态地为目标对象添加职责。在Spring AOP中,MethodInterceptor
可以用来实现装饰模式。以下是相关源码的简要分析:
public class MethodInvocation {
private final List<MethodInterceptor> interceptors;
private int currentInterceptorIndex = -1;
public Object proceed() throws Throwable {
if (this.currentInterceptorIndex == this.interceptors.size() - 1) {
return this.method.invoke(this.target, this.arguments);
}
MethodInterceptor interceptor = this.interceptors.get(++this.currentInterceptorIndex);
return interceptor.invoke(this);
}
}
public class TransactionInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
TransactionStatus status = this.transactionManager.getTransaction(new DefaultTransactionDefinition());
Object retVal;
try {
retVal = invocation.proceed();
this.transactionManager.commit(status);
} catch (Throwable ex) {
this.transactionManager.rollback(status);
throw ex;
}
return retVal;
}
}
- 分析代码片段的功能:
MethodInvocation
类的proceed
方法会顺序执行所有MethodInterceptor
,最终执行目标方法。TransactionInterceptor
是一个具体的MethodInterceptor
,在目标方法执行前后添加事务管理逻辑。
设计思想:
装饰模式通过一个装饰对象来包裹目标对象,动态地为目标对象添加新的功能,而不改变其接口。
解决的问题:
- 动态职责:在不改变目标对象的情况下,动态地添加或改变其功能。
- 职责分离:不同的功能由不同的装饰类实现,职责分离清晰。
优缺点:
- 优点:
- 灵活性:可以在运行时为对象添加新的功能,增强了代码的灵活性。
- 职责分离:不同的装饰类负责不同的功能,职责分离明确。
- 缺点:
- 复杂性:装饰链过长时,会增加代码的复杂性和理解难度。
- 性能开销:多层装饰会带来额外的性能开销。
总结
Spring AOP模块通过使用代理模式和装饰模式,实现了切面功能的灵活扩展。代理模式通过动态代理为目标对象添加功能,保持了代码的透明性和灵活性。装饰模式通过装饰类为目标对象动态添加职责,实现了职责分离和代码复用。这两种模式的结合,使得Spring AOP能够在不改变目标对象的情况下,实现各种切面功能,增强了代码的可维护性和可扩展性。