概念了解:
Spring AOP面向切面编程、动态代理的理解
深入理解SpringAOP中的动态代理
JVM的动态代理特性
在Spring AOP实现中,使用的核心技术是动态代理,这种动态代理实际上是JDK的一个特性。通过JDK的动态代理特性,可以为任意Java对象创建代理对象,通过Java Reflection API来完成。
在代理模式的的设计中,会设计一个接口和目标对象一致的对象Proxy,它们都实现了同一个接口的方法。对目标对象方法的调用,往往就被代理对象给拦截了,通过这种拦截,为目标对象方法操作做了铺垫,称为代理模式。
配置ProxyFactoryBean
以ProxyFactoryBean的实现为例,一起来了解springAOP的具体设计和实现。ProxyFactoryBean可以在IOC容器中完成声明式配置,而使用ProxyFactory则需要编程式地使用spring AOP功能。
ProxyFactoryBean是在springIoC环境中创建AOP应用的底层方法,spring通过它完成了对AOP使用的封装。
ProxyFactoryBean的配置和使用
- 定义使用的通知器Advisor,这个通知器应该作为一个Bean来定义,这个通知器的实现定义了需要对目标对象进行增强的切面行为,也就是Advice通知。
- 在配置ProxyFactoryBean时,需要设定与AOP实现相关的重要属性,如ProxyInterface、InterceptorNames和target等。
- 定义target属性,作为target属性注入的Bean,是需要用AOP通知器的切面应用来增强的对象。
<bean id="testAdvisor" class="com.example.spring.TestAdvisor"/>
<bean id="testAOP" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>
com.example.AbcInterface
</value>
</property>
<property name="interceptorNames">
<list>
<value>testAdvisor</value>
</list>
</property>
</bean>
ProxyFactoryBean生成AOpProxy代理对象
ProxyFactoryBean是一个FactoryBean,在ProxyFactoryBean中,通过interceptorNames属性来配置已经定义好的通知器Advisor,供AOP应用配置通知器的地方。
ProxyFactoryBean需要为target目标对象生成Proxy代理对象,从而为AOP横切面的编织做好准备工作。这些具体的代理对象生成工作,是通过JDK的Proxy或CGLIB来完成的。
ProxyFactoryBean的AOP实现需要依赖JDK或CGLIB提供的Proxy特性。从FactoryBean中获取对象,是以getObject方法作为入口完成的。
ProxyFactoryBean实现中的getObject方法是FactoryBean需要实现的接口,对ProxyFactoryBean来说,把需要对target目标对象增加的增强处理,都通过getObject方法进行封装了,这些增强视为AOP功能的实现提供服务的。
getObject方法首先对通知器链进行初始化,通知器链封装了一系列的拦截器,这些拦截器都要从配置中读取,然后为代理对象的生成做好准备,再生成代理对象时,因为spring对Bean由singleton和prototype之分,座椅要对代理对象的生成做一个区分。
/**
* 返回代理。当客户从该FactoryBean获得bean时调用。 创建要由该工厂返回的AOP代理的实例。
*/
@Override
@Nullable
public Object getObject() throws BeansException {
// 初始化通知器链
initializeAdvisorChain();
// 对singletion和prototype类型进行区分,生成对应的proxy
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}
初始化通知器链
为Proxy代理对象配置Advisor链是在initializeAdvisorChain方法中完成的。
这个初始化过程有一个标志位AdvisorChainInitialized
,用来表示通知器链是否已经初始化,也就是说这个初始化的工作发生在应用第一次通过ProxyFactoryBean去获取代理对象的时候。
在完成这个初始化之后,接着会读取配置中出现的所有通知器,这个过程把通知器的名字交给容器的getBean方法就可以了,通过对IoC容器的一个回调来完成,然后把IoC容器中去的的通知器介入拦截器链中,这个动作由addAdvisorOnChainCreation
方法来实现。
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));
}
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");
}
// 添加Advisor链的调用,通过interceptorNames属性进行配置的
for (String name : this.interceptorNames) {
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
addGlobalAdvisors((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
else {
// 如果程序在这里被调用,那么需要加入命名的拦截器advice
// ,并且需要检查这个Bean是singleton耗时prototype
Object advice;
// 如果是单例Bean 则将真正的Advisor / Advice添加到链中
if (this.singleton || this.beanFactory.isSingleton(name)) {
// Add the real Advisor/Advice to the chain.
advice = this.beanFactory.getBean(name);
}
else {
// 如果是prototype 用原型Bean Advisor代替
advice = new PrototypePlaceholderAdvisor(name);
}
// 添加到链中
addAdvisorOnChainCreation(advice);
}
}
}
this.advisorChainInitialized = true;
}
生成单例Bean代理对象
生成singleton的代理对象在getSingletonInstance()中完成,这个方法是ProxyFactoryBean生成AopProxy代理对象的调用入口,代理对象会封装对target目标对象的调用,也就是说针对target对象的方法调用行为会被这里生成的代理对象所连接。
/**
* 返回代理对象,如果没有创建则延迟创建
*/
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.
// 根据AOP框架来判断需要代理的接口
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.
// 使用ProxyFactoryBean来生成需要的Proxy
super.setFrozen(this.freezeProxy);
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
这里出现了AopProxy类型的对象,spring利用这个AopProxy接口类把AOP代理对象的实现与框架的其他部分有效地分离开来,它有两个实现类,一个是
Cglib2AopProxy
另一个是JdkDynamicProxy
,对这两个AopProxy接口的子类的实现,spring分别通过CGLIB和JDK来生成需要的Proxy代理对象。
ProxyCreatorSupport生成AopProxy对象
具体的代理对象生成,是在ProxyFactoryBean的基类AdvisorSupport的实现中借助AopProxyFactory完成的。至于生成什么样的代理对对象,所有信息都封装在AdvisorSupport里,这个对象也是生成AopProxy的方法的输入参数。
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// 通过AopProxyFactory取得AopProxy,AopProxyFactory是在初始化函数中定义的,
// 使用的是DefaultAopProxyFactory
return getAopProxyFactory().createAopProxy(this);
}
这里使用了AopProxyFactory来创建AopProxy,AopProxyFactory使用的是DefaultAopProxyFactory,这个被使用的AopProxyFactory作为AopProxy的创建工厂对象,在ProxyFactoryBean的基类ProxyCreatorSupport中被创建,在创建AopProxyFactory时,它被设置为DefaultAopProxyFactoryBean,问题就转换为在DefaultAopProxyFactory中,AopProxy是怎样生成的了。
在DefaultAopProxyFactory中创建AopProxy
对于AopProxy代理对象的生成,需要考虑使用哪种生成方式,如果目标对象是接口类,那么适合使用JDK来生成代理对象,否则spring会使用CGLIB来生成目标对象的代理对象。
DefaultAopProxyFactory创建AopProxy的过程是一个比较高层次的AopProxy代理对象的生成过程,对不同的AopProxy代理对象的生成所涉及的生成策略和场景做相应设计,但是对于具体的AopProxy代理对象的生成,最终并没有由DefaultAopProxyFactory来完成,而是由spring封装的jdkDynamicAopProxy
和CglibProxyFactory
;类来完成的。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!IN_NATIVE_IMAGE &&
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
// 从AdvisedSupport对象中取得配置的目标对象
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.");
}
// 如果tatgetClass是接口类,使用JDK来生成Proxy
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 如果不是接口类 使用CGLIB来生成Proxy
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
目标对象可以看做是皮,而AOP完成的是切面增强就是依附在这块皮上的毛。
JDK生成AopProxy代理对象
ProxyFactoryBean在AopProxy代理对象和IoC容器配置之间起到了桥梁的作用,体现在它为代理对象的最终生成做好了准备。
在JDKDynamicAopProxy中,使用了JDK的Proxy类来生成代理对象,在生成Proxy对象之前,首先需要从Advised对象中取得代理对象的代理借口配置,然后调用Proxy的newProxyInstance方法,最终得到对应的Proxy代理对象。
在生成代理对象时,需要指明三个参数,一个类装载器,一个代理接口,另外一个就是Proxy回调方法所在的对象,这个对象需要实现InvocationHandler
接口,这个InvocationHandler
接口定义了invoke方法,提供代理对象的回调入口。
对于JdkDynamicAopProxy
,它本身实现了InvocationHandler接口和invoke方法,这个invoke方法是Proxy代理对象的回调方法,所以可以使用this来把JDKDynamicAopProxy指派给Proxy对象,也就是说JDKDynamicAopProxy对象本身,在Proxy代理的几口方法被调用时,会触发invoke方法的回调,这个回调方法完成了AOP编织实现的封装。
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
// 调用JDK生成proxy的地方
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
CGLIB生成AopProxy代理对象
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
// 从advised中取得在IOC容器中配置的target对象
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
// 验证代理对象的接口设置
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
// 创建并配置CGLIB的Enhancer 这个Enhancer对象时CGLIB的主要操作类
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
// 设置Enhancer对象,包括设置代理接口,回调方法
// 来自advised的IoC配置 比如使用AOP的DynamicAdvisedInterceptor拦截器
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
// 通过Enhancer生成代理对象
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
通过对Enhancer对象生成代理对象的过程,在这个生成代理对象的过程中,需要注意的是对Enhancer对象callback回调的设置,正是这些回调封装了Spring AOP的实现,就像JDK的Proxy对象的invoke回调方法一样。在Enhancer的callback回调设置中,实际上是通过DynamicAdvisedInterceptor
拦截器来完成AOP功能的。
对target目标对象的方法调用会首先被AopProxy代理对象拦截,对于不同AopProxy代理对象生成方式,会使用不同的拦截回调入口。对于JDK的AopProxy代理对象,使用
InvocationHandler
的invoke回调入口,而对于CGLIB的AopProxy代理对象,使用的是设置好的callback回调,这是由对CFLIB的使用来决定的。
Spring AOP拦截器调用的实现
设计原理
在spring AOP通过JDK的Proxy方法或者CGLIB方式生成代理对象的时候,相关拦截器已经配置到代理对象中去了,拦截器在代理对象中起作用是通过这些方法的回调来完成的。
如果使用JDK的Proxy来生成代理对象,那么需要通过InvocationHandler来设置拦截器回调,而如果使用CGLIB来生成代理像,就需要根据CGLIB的使用要求,通过DynamicAdviseInterCeptor来完成回调。
JDKDynamicAopProxy的invoke拦截
在JDKDynamicAopProxy中生成Proxy对象时,它的AopProxy代理对象的生成调用:
Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
这里的this参数对应的是InvocationHandler对象,InvocationHandler是JDK定义的反射类的一个接口,这个接口定义了invoke方法,而这个invoke方法是作为JDK Proxy代理对象进行拦截的回调入口实现的。
当Proxy对象的代理方法被调用时,JDKDynamicAopProxy的invoke方法作为Proxy对象的回调函数被触发。
对Proxy对象的代理设置是在invoke方法中完成的,这些设置包括获取目标对象、拦截器链,同时把这些对象作为输入,创建ReflectiveMethodInvocation
对象,通过这个对象来完成AOP功能实现的封装。在这个invoke方法中,包含了一个完成的拦截器链对目标对象的拦截过程。比如获得拦截器链并对拦截器链中的拦截器进行配置,逐个运行拦截器链里的拦截增强,知道最后对目标对象方法的运行等。
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 如果目标对象没有实现Object类的equals方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
// 如果目标对象没有实现Object类的hashcode方法
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
// 如果目标类为装饰器代理子类
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
// 根据代理对象的配置来调用服务
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 得到目标对象
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获得定义改的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 如果没有设定拦截器 则直接调用target的对应方法
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 如果有拦截器设定,那么需要调用拦截器之后才调用目标对象相应方法
MethodInvocation 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 != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
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);
}
}
}
Cglib的Intercept拦截
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 从advised中取得配置好的AOP通知
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// 如果没有AOP通知配置,那么直接调用target对象的调用方法
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// 通过CglibMethodInvocation来启动advice通知
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
目标对象方法的调用
如果没有设置拦截器,那么会对目标对象的方法直接进行调用,对于JDKDynamicAopProxy代理对象,这个目标对象的方法调用是通过AopUtils使用反射机制在AopUtils.invokeJoinpointUsingReflection
中实现的。
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
throws Throwable {
// Use reflection to invoke the method.
// 使用反射调用target对象方法的地方
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.
// 抛出AOP异常,对异常进行类型转换
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);
}
}
CGLIB代理对目标对象的调用是通过CGLIB的MethodProxy对象来直接完成的,这个对象的使用是由CGLIB的设计决定的。具体的调用在DynamicAdvisedInterceptor
的Intercept方法中可以看到。retVal = methodProxy.invoke(target, argsToUse);
AOP拦截器链的调用
AOP是怎样完成对目标对象的增强的,这些实现封装在AOP拦截器链中,由一个个具体的拦截器来完成。
虽然jdk代理和cglib代理使用了不同的AopProxy代理对象,但最终对AOP拦截的处理殊途同归,它们对拦截器链的调用都是在ReflectiveMethodInvocation
中通过proceed方法实现的。在proceed方法中,会逐个运行拦截器的拦截方法,在运行拦截器的拦截方法之前,需要对代理方法完成一个匹配判断,通过这个匹配判断来决定拦截器是否满足切面增强的要求。
在proceed方法中,先进性判断,如果现在已经运行到拦截器末尾,那么就会直接调用目标对象的实现方法,否则,沿这拦截器链继续进行,得到下一个拦截器,通过这个拦截器进行matches判断,判断是否适用于横切增强的场合。如果是,从拦截器中得到通知器,并启动通知器的invoke方法进行切面增强。这个过程结束以后,会迭代调用proceed方法,直到拦截器链中的拦截器都完成以上的拦截过程为止。
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// 从索引为-1的拦截器开始调用,并按序递增,如果拦截器链中的拦截器迭代调用完毕,这里开始调用target的函数
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 沿这定义好的interceptorOrInterceptionAdvice 链进行处理
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.
// 对拦截器进行动态匹配判断,触发进行匹配的地方,如果和定义的Pointcut匹配,
// 那么这个advice会得到执行
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 {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
// 如果不匹配,那么proceed会被递归调用,直到所有拦截器都被运行过为止
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
// 如果是一个Interceptor 直接调用这个Interceptor对应的方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
配置通知器
AdvisedSupport取得拦截器
利用cache去获取已有的Interceptor链,但是第一次需要自己动手生成,这个Interceptor链的生成是由AdvisorChainFactory完成的,这里使用的是DefaultAdvisorChainFactory。
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable 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;
}
DefaultAdvisorChainFactory生成拦截器链
从名字可以看到该工厂是一个生成通知链的工厂,它实现了Interceptor链的获取过程。
这个过程中,首先设置一个List,其长度是由配置的通知器的个数来决定的,这个配置就是XML中对ProxyFactoryBean做的interceptNames
属性的配置。然后DefaultAdvisorChainFactory会通过一个AdvisorAdapterRegistry
来实现拦截器的注册,有了AdvisorAdapterRegistry
的注册器,利用它来对ProxyFactoryBean配置中得到的通知进行适配,从而获得相应的拦截器,再把它加入前面设置好的List中,完成拦截器注册过程。
在拦截器适配和注册过程完成后,List中的拦截器会被JDK生成的AopProxy代理对象的invoke方法或者CGLIB代理对象的interceptor拦截方法取得,并启动拦截器的invoke调用,最终触发通知的切面增强。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// Advisor链已经在config中持有了,直接使用
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
// 由切入点驱动的所有Advisor的接口。 这几乎涵盖了除介绍拦截器之外的所有拦截器,不适用于方法级匹配
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
// 判断该拦截器是否静态匹配
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
if (match) {
// 获取到达目标的接口上的拦截调用
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
// 拦截器是否运行时调用
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));
}
}
}
}
// 执行一个或多个AOP拦截器的接口
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;
}
/**
* 判断Advisors是否符合配置要求
* Determine whether the Advisors contain matching introductions.
*/
private static boolean hasMatchingIntroductions(Advisor[] advisors, Class<?> actualClass) {
for (Advisor advisor : advisors) {
if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (ia.getClassFilter().matches(actualClass)) {
return true;
}
}
}
return false;
}
在拦截器链的初始化中获取Advisor通知器
在ProxyFactoryBean的getObject方法中对Advisor进行初始化时,从XML配置中获取了Advisor通知器。
Advisor通知器的取得是委托给IoC容器完成的,但是在ProxyFactoryBean中是如何获得IoC容器,然后通过回调IoC容器的getBean方法来得到需要的通知器的呢?
在使用DefaultListableBeanFactory作为IoC容器的时候,它的基类是AbstractAutowireCapableBeanFactory
,在这个积累中有一个对Bean进行初始化的initializeBean
方法,在这个Bean的初始化过程中,对IoC容器在Bean中的回调进行设置。
首先判断这个Bean的类型是不是实现了BeanFactoryAware
接口,如果是,则通过实现的接口方法,把IoC容器设置到Bean自身定义的一个属性中去。这样在这个Bean的自身实现中就能够得到它所在的IoC容器,从而掉用IoC容器的getBean方法,完成对IoC容器的回调。除了使用为自己设计的功能外,还可以调用它所在的容器的功能。
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
对于IoC容器的使用,如果需要回调容器,前提是当前Bean需要实现BeanFactoryAware接口,这个接口只需要实现setBeanFactory
方法同时设置一个属性来只有BeanFactory的IoC容器,就可以在Bean中取得IoC容器进行回调了,在IoC容器对Bean进行初始的时候,对Bean进行判断,如果是BeanFactoryAware类型,则会将IoC设置到这个Bean中,设置好以后,ProxyFactoryBean就可以通过回调同期的getBean去获取配置在Bean定义文件中的通知器了,获取通知器就是向IoC容器回调getBean的过程。
ProxyFactoryBean需要给出通知器的名字,而这些名字都是在InterceptorNames的List中配置好的,在IoC对FactoryBean进行依赖注入的时候,会直接注入到FactoryBean的InterceptorNames属性中,完成这个过程后,ProxyFactoryBean就获得了配置的通知器,为完成切面增强做好准备。
Advice通知的实现
前面了解到,在生成拦截器链的过程中,有一个适配和注册的过程,通过配置spring预计设计好的拦截器,spring加入了它对AOP实现的处理。为了详细了解这个过程,先从DefaultAdvisorChainFactory
的实现开始,首先构造了一个GlobalAdvisorAdapterRegistry
单例对象,然后对配置的Advisor通知器进行逐个辨别能力,这个通知器链都是配置在InterceptorNames中的,从getInterceptorsAndDynamicInterceptionAdvice
传进来的advised参数对象汇总可以方便获取配置的通知器,有了这些通知器,接着就是一个由GlobalAdvisorAdapterRegistry
来完成的拦截器的适配和注册过程。
// 得到注册器 单例模式实现的
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
它的实例是一个DefaultAdvisorAdapterRegistry
。
public final class GlobalAdvisorAdapterRegistry {
private GlobalAdvisorAdapterRegistry() {
}
private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();
}
在DefaultAdvisorAdapterRegistry
中,设置了一系列adapter适配器,正是这些adapter适配器的实现,为spring AOP的advice提供编织能力。
这些adapter的使用主要体现在以下两个方面:
- 调用adapter的support方法,通过这个方法来判断取得的advice属于什么类型的advice通知,从而根据不同的advice类型类注册不同的AdviceInterceptor,也就是前面的拦截器。
- 这些AdviceInterceptor都是Spring AOP框架设计好了的,是为实现不同的advice功能提供服务的,有了这些AdviceInterceptor,可以方便地使用spring提供的各种不同的advice来设计AOP应用。
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
/**
* 持有一个AdvisorAdapter的List 这个List中的Adapter是与实现spring AOP的advice增强功能相对应的
*/
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
/** 把已有的advice实现的Adapter加入进来
* 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<>(3);
// 从Advisor通知器配置中取得advice通知
Advice advice = advisor.getAdvice();
// 如果通知是MethodInterceptor类型的通知,直接加入interceptors的List 不需要适配
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
// 对通知进行适配 使用已经配置好的Adapter,然后从对应的adapter中取出封装好AOP编织功能的拦截器
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]);
}
@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
}
在DefaultAdvisorAdapterRegistry
的getInterceptors调用中,从MethodBeforeAdviceAdapter
、AfterReturningAdviceAdapter
和ThrowsAdviceAdapter
这几个通知适配器的名字可以看到,他们和advice意义对应,这里作为适配器被加入到adapter的List中,从这及各类的设计层次和关系看,它们都是实现AdvisorAdapter接口的同一层次类,只是承担着不同的适配任务,一对一服务于不同advice实现。
以MethodBeforeAdviceAdapter
为例,它实现了AdvisorAdapter的两个接口方法,一个是supportsAdvice,对advice类型进行判断,另一个是对getInterceptor接口方法的实现,这个方法把advice通知从通知器中取出,然后创建一个MethodBeforeAdviceInterceptor对象,通过这个对象把取得的advice通知包装起来。
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);
}
}
MethodBeforeAdviceInterceptor
的实现
springAOP为了实现advice的织入设计了特定的拦截器对这些功能进行了封装,以MethodBeforeAdviceInterceptor
为例,它是如何完成advice的封装的。
在invoke回调方法中,首先触发了advice的before回调,然后才是MethodInvocation的proceed方法调用。
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
/**
* 为指定的Advice创建对应的MethodBeforeAdviceInterceptor
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
@Nullable
/**
* 这个invoke方法是拦截器的回调方法,会在代理对象的方法被调用时触发回调
*/
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}
AfterReturnAdviceInterceptor
的实现
对于其他的advice通知也可以举一反三,如AfterReturnAdviceInterceptor
的实现,先完成MethodInvocation
的proceed调用,也就是目标对象的方法调用,然后再启动advice通知afterReturning回调。
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
private final AfterReturningAdvice advice;
public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
}
ThrowsAdviceInterceptor
的实现
相比于其余两个拦截器,它维护了一个exceptionHandlerMap
来对应不同的方法调用场景。
public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {
private static final String AFTER_THROWING = "afterThrowing";
private static final Log logger = LogFactory.getLog(ThrowsAdviceInterceptor.class);
private final Object throwsAdvice;
/** Methods on throws advice, keyed by exception class. */
private final Map<Class<?>, Method> exceptionHandlerMap = new HashMap<>();
public ThrowsAdviceInterceptor(Object throwsAdvice) {
Assert.notNull(throwsAdvice, "Advice must not be null");
this.throwsAdvice = throwsAdvice;
// 配置ThrowsAdvice的回调方法
Method[] methods = throwsAdvice.getClass().getMethods();
for (Method method : methods) {
if (method.getName().equals(AFTER_THROWING) &&
(method.getParameterCount() == 1 || method.getParameterCount() == 4)) {
Class<?> throwableParam = method.getParameterTypes()[method.getParameterCount() - 1];
if (Throwable.class.isAssignableFrom(throwableParam)) {
// An exception handler to register...
this.exceptionHandlerMap.put(throwableParam, method);
if (logger.isDebugEnabled()) {
logger.debug("Found exception handler method on throws advice: " + method);
}
}
}
}
// 配置异常处理
if (this.exceptionHandlerMap.isEmpty()) {
throw new IllegalArgumentException(
"At least one handler method must be found in class [" + throwsAdvice.getClass() + "]");
}
}
public int getHandlerMethodCount() {
return this.exceptionHandlerMap.size();
}
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
try {
// 把对目标对象的方法调用放入try/catch 中,并在catch中触发ThrowsAdvice的回调
// 把异常接着向外抛出,不做过多处理
return mi.proceed();
}
catch (Throwable ex) {
Method handlerMethod = getExceptionHandler(ex);
if (handlerMethod != null) {
invokeHandlerMethod(mi, ex, handlerMethod);
}
throw ex;
}
}
@Nullable
private Method getExceptionHandler(Throwable exception) {
Class<?> exceptionClass = exception.getClass();
if (logger.isTraceEnabled()) {
logger.trace("Trying to find handler for exception of type [" + exceptionClass.getName() + "]");
}
Method handler = this.exceptionHandlerMap.get(exceptionClass);
while (handler == null && exceptionClass != Throwable.class) {
exceptionClass = exceptionClass.getSuperclass();
handler = this.exceptionHandlerMap.get(exceptionClass);
}
if (handler != null && logger.isTraceEnabled()) {
logger.trace("Found handler for exception of type [" + exceptionClass.getName() + "]: " + handler);
}
return handler;
}
// 通过反射启动对ThrowsAdvice回调方法的调用
private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable {
Object[] handlerArgs;
if (method.getParameterCount() == 1) {
handlerArgs = new Object[] {ex};
}
else {
handlerArgs = new Object[] {mi.getMethod(), mi.getArguments(), mi.getThis(), ex};
}
try {
method.invoke(this.throwsAdvice, handlerArgs);
}
catch (InvocationTargetException targetEx) {
throw targetEx.getTargetException();
}
}
}
ProxyFactory实现AOP
除了使用ProxyFactoryBean实现AOP应用之外,还可以使用ProxyFactory来实现Spring AOP功能,只是在使用ProxyFactory的时候,需要编程式完成AOP应用的设置。
与ProxyFactoryBean实现AOP相比,ProxyFactory没有使用FactoryBean的IoC封装,而是通过直接继承ProxyCreatorSupport
的功能来完成AOP的属性配置。
同样获取代理对象的时候也是以getProxy为入口,由DefaultAopProxyFactory
来完成的。