Spring系列-Spring AOP原理分析
先了解一些AOP的概念:
1.Advice(通知)
定义在连接点做什么,为切面增强提供织入接口。比如BeforeAdvice,AfterAdvice等。可以定义在方法执行前或执行后需要做的操作。
2.Pointcut(切点)
定义Advice通知应该作用于哪个连接点。
比如这个JdkRegexpMethodPointcut,就是通过正则表达式是否匹配来判断是否作用于这个Adivce的。
3.Advisor(通知器)
Advisor是Advice和Pointcut的结合,定义了应该使用哪个Advice,并且定义了在哪个Pointcut使用。也就是说,定义了在哪个条件用哪个Advice。
Spring AOP的实现,用到了动态代理,所以还要对动态代理有个了解,我之前在一篇帖子中也总结过JDK动态代理的用法:动态代理总结
Java已经提供了Proxy类,一般情况下,我们通过Proxy.newProxyInstance方法,就可以创建一个代理对象了。
那Spring AOP的原理是啥呢,我们定义了Advisor之后,如何起作用呢。
先说下结论吧,我们用了Advisor,来定义了我们要为某个类在满足某些条件的时候增强,当我们在使用这个类的对象时候,Spring AOP就会为这个类生成一个代理对象,并且把我们在Advice里面定义的操作都封装成一个个的拦截器,当我们调用方法的时候,就会先经过这些拦截器,然后再通过反射来调用真正的方法。
Spring AOP模块关于生成代理对象时,会涉及到下面这些类。
对于需要使用AspectJ的AOP应用,AspectJProxyFactory就可以集成Spring和AspectJ,对于使用Spring AOP的应用,ProxyFactoryBean和ProxyFactory都提供了AOP的封装,不同的是,ProxyFactoryBean可以在IoC容器中完成声明式的配置,而ProxyFactory需要编程式的使用。
接下来看下ProxyFactoryBean,使用ProxyFactoryBean之前需要配置,定义使用的通知器Advisor,定义target等,这里就不再详细说明,关键去看代码。
接下来,看一下ProxyFactoryBean如何生成代理对象的,看ProxyFactoryBean类的代码,很明显可以看到一个getObject方法,注释写的是返回一个proxy,那就是它了:
/**
* Return a proxy. Invoked when clients obtain beans from this factory bean.
* Create an instance of the AOP proxy to be returned by this factory.
* The instance will be cached for a singleton, and create on each call to
* {@code getObject()} for a proxy.
* @return a fresh AOP proxy reflecting the current state of this factory
*/
@Override
public Object getObject() throws BeansException {
initializeAdvisorChain();
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}
getObject里面,能够看到主要有三个方法,第一个是initializeAdvisorChain,这个是初始化Advisor链的,接下来,还需要判断一下,对于singleton和prototype来说,需要调用不同的方法来生成proxy。
那就先看下initializeAdvisorChain的逻辑:
/**
* Create the advisor (interceptor) chain. Advisors that are sourced
* from a BeanFactory will be refreshed each time a new prototype instance
* is added. Interceptors added programmatically through the factory API
* are unaffected by such changes.
*/
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
// 判断通知器链是否已经初始化,如果已经初始化了,就直接返回。
if (this.advisorChainInitialized) {
return;
}
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
}
// Globals can't be last unless we specified a targetSource using the property...
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}
// Materialize interceptor chain from bean names.
for (String name : this.interceptorNames) {
if (logger.isTraceEnabled()) {
logger.trace("Configuring advisor or advice '" + name + "'");
}
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
else {
// If we get here, we need to add a named interceptor.
// We must check if it's a singleton or prototype.
Object advice;
if (this.singleton || this.beanFactory.isSingleton(name)) {
// Add the real Advisor/Advice to the chain.
advice = this.beanFactory.getBean(name);
}
else {
// It's a prototype Advice or Advisor: replace with a prototype.
// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
advice = new PrototypePlaceholderAdvisor(name);
}
addAdvisorOnChainCreation(advice, name);
}
}
}
this.advisorChainInitialized = true;
}
这个方法是初始化通知器链的,我们定义的那些Advisor,就会在这里进行处理,顺着代码一直跟下去的话,就会发现,会把Advisor添加到AdvisedSupport类的advisors字段。
/**
* List of Advisors. If an Advice is added, it will be wrapped
* in an Advisor before being added to this List.
*/
private List<Advisor> advisors = new LinkedList<Advisor>();
通知器链初始化完成之后,再看下如何返回singleton的proxy,进去getSingletonInstance方法看一下:
/**
* Return the singleton instance of this class's proxy object,
* lazily creating it if it hasn't been created already.
* @return the shared singleton proxy
*/
private synchronized Object getSingletonInstance() {
// 先从缓存中获取,如果获取到的话,就可以直接返回了。
if (this.singletonInstance == null) {
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
// 设置代理对象的接口
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// Initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
这里比较重要的是this.singletonInstance = getProxy(createAopProxy());这行代码,这里就是生成代理对象的地方。
其中,createAopProxy()先返回一个代理类,getProxy方法再根据这个代理类,返回一个代理对象。
先进去createAopProxy方法看下,createAopProxy方法在ProxyCreatorSupport类中。
/**
* Subclasses should call this to get a new AOP proxy. They should <b>not</b>
* create an AOP proxy with {@code this} as an argument.
*/
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (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);
}
}
createAopProxy()中先调用了getAopProxyFactory()方法获取AopProxyFactory,然后再调用createAopProxy(AdvisedSupport config)方法创建一个代理类。
createAopProxy()方法返回AopProxy类型的对象,AopProxy是个接口,JdkDynamicAopProxy和CglibAopProxy都是它的实现类:
在createAopProxy(AdvisedSupport config)中,返回AopProxy的时候,也会进行判断,如果目标类是个接口,则返回JdkDynamicAopProxy,还有一些情况返回ObjenesisCglibAopProxy。
顾名思义,JdkDynamicAopProxy是利用的jdk的proxy来创建的代理类,实现了InvocationHandler接口,重写了invoke方法:
/**
* Implementation of {@code InvocationHandler.invoke}.
* <p>Callers will see exactly the exception thrown by the target,
* unless a hook method throws an exception.
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null. Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
// 获取目标对象
target = targetSource.getTarget();
if (target != null) {
// 获取目标类
targetClass = target.getClass();
}
// Get the interception chain for this method.
// 获取拦截器链,我们一开始初始化了通知器链,这里会把通知器链转换为拦截器链。
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
// 如果没有定义拦截器,则直接调用目标类的相应方法
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
// 如果定义了拦截器,先执行拦截器中的方法。
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
所以,Spring AOP的主要实现逻辑,在这里就能看出来了,生成代理类的时候,在invoke方法里面,把定义的那些通知器转换为拦截器,然后在调用目标对象的方法之前,先调用拦截器中的方法,面向切面编程的效果就有了。
把我们定义的通知器,转换为拦截器,是在getInterceptorsAndDynamicInterceptionAdvice方法中实现的:
/**
* Determine a list of {@link org.aopalliance.intercept.MethodInterceptor} objects
* for the given method, based on this configuration.
* @param method the proxied method
* @param targetClass the target class
* @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
*/
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
这个方法会把我们的通知器链,转换为拦截器链返回。接下来,还是看invoke中的逻辑,获取到拦截器链之后,如果拦截器链为空,则通过反射,调用目标类的方法:
/**
* Invoke the given target via reflection, as part of an AOP method invocation.
* @param target the target object
* @param method the method to invoke
* @param args the arguments for the method
* @return the invocation result, if any
* @throws Throwable if thrown by the target method
* @throws org.springframework.aop.AopInvocationException in case of a reflection error
*/
public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
throws Throwable {
// Use reflection to invoke the method.
try {
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
}
catch (InvocationTargetException ex) {
// Invoked method threw a checked exception.
// We must rethrow it. The client won't see the interceptor.
throw ex.getTargetException();
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
method + "] on target [" + target + "]", ex);
}
catch (IllegalAccessException ex) {
throw new AopInvocationException("Could not access method [" + method + "]", ex);
}
}
如果拦截器链不为空的话,则调用MethodInvocation的proceed方法,我们这里的MethodInvocation的实现类是ReflectiveMethodInvocation:
@Override
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
这个proceed方法从索引为-1的拦截器开始调用,对当前的拦截器,先调用matches方法判断是否匹配(这个就是每个Pointcut定义的条件),如果匹配的话,就调用拦截器的invoke方法,不匹配的话,就继续调用proceed方法。
看到这里,基本上AOP的实现逻辑就差不多了,以JdkDynamicAopProxy的逻辑来说,就是创建了一个代理类,代理类中的invoke方法里面去调用拦截器。然后通过Proxy.newProxyInstance方法,创建一个代理对象。
关于JdkDynamicAopProxy还有个细节说下,就是把我们定义的通知器转换成拦截器的地方,在getInterceptorsAndDynamicInterceptionAdvice方法中,主要是这句话:
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
这里是调用了AdvisorAdapterRegistry的getInterceptors方法,把Advisor转换成了拦截器列表。这里的AdvisorAdapterRegistry是用的DefaultAdvisorAdapterRegistry,进去DefaultAdvisorAdapterRegistry类里看下:
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);
/**
* Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
*/
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(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[interceptors.size()]);
}
@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
}
在getInterceptors中,先从通知器中获取定义的Advice,如果Advice是MethodInterceptor类型的话,就直接强转,如果不是的话,就调用adapter.getInterceptor(advisor)方法进行转换。在DefaultAdvisorAdapterRegistry构造方法中可以看到对adapters的赋值,把MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter、ThrowsAdviceAdapter这三个Adapter添加到了adapters中。
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);
}
}
class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof AfterReturningAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
return new AfterReturningAdviceInterceptor(advice);
}
}
class ThrowsAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof ThrowsAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
return new ThrowsAdviceInterceptor(advisor.getAdvice());
}
}
可以看到这三个Adapter的实现,MethodBeforeAdviceAdapter的getInterceptor方法会返回一个MethodBeforeAdviceInterceptor,AfterReturningAdviceAdapter的getInterceptor方法会返回一个AfterReturningAdviceInterceptor,ThrowsAdviceAdapter的getInterceptor方法会返回一个ThrowsAdviceInterceptor。
返回这些过滤器后,在invoke方法的proceed方法中,如果matches了,就会调用interceptor的invoke方法,所以,可以看下MethodBeforeAdviceInterceptor类的代码:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
private MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @param advice the MethodBeforeAdvice to wrap
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
}
MethodBeforeAdviceInterceptor的invoke方法,会先调用Advice的before方法,然后再调用mi.proceed()方法,继续拦截器链的逻辑。其它Interceptor的代码逻辑也类似,这里就不详细看了。
看到现在,Spring AOP的原理实现基本就清楚了。我们定义的各种不同的Advice,会转换成不同的拦截器,在invoke中依次被调用。通过CGLib返回代理对象的逻辑虽然有些不同,但是基本上都一样的,这里也就不再详细分析了。
参考资料:
1.《Spring技术内幕》 计文柯 著