Java是面向对象的编程语言,整个程序的执行是方法纵向的调用完成,Aop是面向切面的编程思想,是对面向对象的一个补充。Aop面向切面的思想是针对方法进行编程,依赖动态代理来实现对方法执行的前后注入业务逻辑。简而言之,spring aop是面向切面的编程思想,辅佐以动态代理的实现来完成。
下面以ProxyFactoryBean的getObject为切入点,来分析spring aop的实现原理。
获取通知器链
从ProxyFactoryBean的getObject方法中可以看到,initializeAdvisorChain初始化通知器链,这个是通过读取interceptorNames的配置属性获取的,然后把获取到的所有通知器添加到通知器链中,这里是按配置的顺序进行添加的。最后是把所有通知器链保存到advisors属性中。
public Object getObject() throws BeansException {
//从ProxyFactoryBean的配置中获取所有的advisor信息
initializeAdvisorChain();
if (isSingleton()) {
//获取代理对象
return getSingletonInstance();
}
// ...
}
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
// ...
for (String name : this.interceptorNames) {
if (name.endsWith(GLOBAL_SUFFIX)) {
addGlobalAdvisors((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
else {
Object advice;
if (this.singleton || this.beanFactory.isSingleton(name)) {
//这里从spring ioc容器中获取通知bean
advice = this.beanFactory.getBean(name);
}
else {
advice = new PrototypePlaceholderAdvisor(name);
}
//把获取到的通知添加到通知器链中,这里是按序添加的
addAdvisorOnChainCreation(advice);
}
}
}
this.advisorChainInitialized = true;
}
代理对象的生成
aop代理对象的生成是委托给AopProxy来进行代理对象的生成。
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
//生成一个aop代理对象
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//配置了isProxyTargetClass属性或者没有实现接口就使用ObjenesisCglibAopProxy去生成代理对象,否则就使用JdkDynamicAopProxy生成代理对象
if (!NativeDetector.inNativeImage() &&
(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);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
}
这里可以看到,spring把代理对象的生成是交给了AopProxy接口,通过AopProxy来解耦了代理对象的生成。在配置了isOptimize或isProxyTargetClass的时候,并且目标对象不是实现接口的形式,就采用ObjenesisCglibAopProxy来生成代理对象,否则就使用JdkDynamicAopProxy去生成代理对象。对于代理对象这里是动态代理设计模式的使用,对于动态代理对象这里不进行解释,以JdkDynamicAopProxy为例来看看代理对象的生成过程。
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override
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);
}
}
在代理模式中,Proxy生成代理对象的时候,需要传入类加载器、目标对象实现的接口和触发器。代理对象生成后,对目标对象所有的方法调用都会交给InvocationHandler进行处理,都会触发InvovationHandler接口invoke方法的调用。JdkDynamicAopProxy实现了InvocationHandler接口,所以这里在生成代理对象的时候,把自己作为InvocationHandler参数传进去了。
以上是为实现spring aop进行的基础处理和铺垫:
- 读取配置的通知器到advisors通知器链中
- 代理对象的生成
接下来看看在实际方法调用的过程中,aop是怎么对运行的方法进行拦截处理的。对目标方法的调用最终都会转交给InvocationHandler的invoke方法的处理,以这个为入口进行分析。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
// ...
//获取通知器链
List
这里是先获取当前方法的通知器链,然后把通知器链包装成ReflectiveMethodInvocation进行调用。
通知器链如何获取
public List
可以看到在获取通知器链的时候,是使用DefaultAdvisorChainFactory来进行获取的。
- 在初始化通知器链的时候,已经把配置的通知器添加到通知器链中了。
- 根据通知器链,通过MethodMatcher来判断通知器对当前方法是否匹配
- 对于匹配的通知器,这里把通知器和MethodMatcher包装成InterceptorAndDynamicMethodMatcher转换成MethodInterceptor添加到拦截器链中。
看看通知器适配成拦截器的过程
DefaultAdvisorAdapterRegistry是用来把advisor转换成MethodInterceptor。
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
}
在DefaultAdvisorAdapterRegistry实例化的时候,添加了3个适配器,由这3个适配器来具体完成对不同的advisor完成Interceptor转换。下面以MethodBeforeAdviceAdapter来分析:
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}
适配器把Advisor转换成MethodBeforeAdviceInterceptor拦截器。
获取完拦截器,看看在方法调用实际运行的时候,拦截器链是怎么起作用的。
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
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) {
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);
}
}
}
沿着拦截器链开始,一个个遍历执行拦截器中的所有拦截器,这里就是前面从通知器适配转换的MethodBeforeAdviceInterceptor拦截器等。
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}
这里就回到了我们自己写的业务通知逻辑。cglib生成的代理对象执行过程和jdk执行过程没有太大的区别。