1. AOP
,AspectJ
,Spring AOP
AOP
AOP
要实现的是在我们原来写的代码的基础上,进行一定的包装,如在方法执行前、方法返回后、方法抛出异常后等地方进行一定的拦截处理或者叫增强处理
AOP
的实现并不是因为 Java 提供了什么神奇的钩子,可以把方法的几个生命周期告诉我们,而是我们要实现一个代理,实际运行的实例其实是生成的代理类的实例
Spring AOP
它基于动态代理来实现。默认地,如果使用接口的,用 JDK
提供的动态代理实现,如果没有接口,使用 CGLIB
实现;Spring AOP
需要依赖于 IOC
容器来管理
AspectJ
属于静态织入,它是通过修改代码来实现的,AspectJ
能干很多 Spring AOP
干不了的事情,它是 AOP
编程的完全解决方案。Spring AOP
致力于解决的是企业级开发中最普遍的 AOP
需求(方法织入),而不是力求成为一个像 AspectJ
一样的 AOP
编程完全解决方案
2. Spring AOP
的设计与实现
目前 Spring AOP
一共有三种配置方式,Spring
做到了很好地向下兼容
-
Spring 1.2
基于接口的配置:最早的Spring AOP
是完全基于几个接口的 -
Spring 2.0 schema-based
配置:Spring 2.0
以后使用XML
的方式来配置,使用 命名空间<aop />
-
Spring 2.0 @AspectJ
配置:使用注解的方式来配置,这种方式感觉是最方便的,还有,这里虽然叫做@AspectJ
,但是这个和AspectJ
其实没啥关系
这里针对Spring 1.2
基于接口的配置完成源码的阅读
Spring AOP
的核心技术是动态代理技术,对于AOP
的使用者来说只需要配置相关的Bean
定义即可,AOP
的内部设计为目标建立代理对象,这个代理对象可以通过使用JDK
的Proxy
来完成,也可以通过第三方的类生成器CGLIB
完成;然后还需要启动代理对象的拦截器来完成各种横切面的织入,这一些列的织入设计是通过一系列Adapter
来实现的,通过一系列的Adapter
的设计,可以把AOP
的横切面设计和Proxy
模式有机地结合起来
3. 建立AopProxy
代理对象
对于Spring
应用,是通过配置和调用Spring
的ProxyFactoryBean
来完成代理对象的生成的,在ProxyFactoryBean中,封装了主要代理对象的生成过程,在生成过程中,可以使用JDK
的Proxy
和CGLIB
两种生成方式
3.1 ProxyFactoryBean
通过上面的类的继承管理可以看到,ProxyFactoryBean
是Spring IOC
环境中创建AOP
应用的底层方法,它完成了具体的AOP
代理对象的创建,提供了AOP
功能的封装,我们可以通过配置来配置目标对象和切面行为;
ProxyFactoryBean
的AOP
实现需要依赖JDK
或CGLIB
提供的Proxy
特性,之后通过getObject()
方法作为入口从FactoryBean
中获取对象,对target
进行增强的增强处理也通过getObject
方法进行封装了
@Override
public Object getObject() throws BeansException {
//初始化通知器链
initializeAdvisorChain();
//对singleton和protoype的类型区分,生成对应的proxy
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
方法中先对通知器链进行了初始化,通知器链封装了一系列的从配置中读取的拦截器,之后对singleton
和protoype
的类型区分,生成对应的proxy
这个为proxy
代理对象配置Advisor
链的过程如下:
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
//advisorChainInitialized标志位 判断是否已经初始化过
//只有第一次通过ProxyFactoryBean获取代理对象才会初始化
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");
}
//通过通知器的名字interceptorName在容器中取得通知器加入通知器链
//取得通知器就是通过容器的getBean方法完成的
// 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;
}
之后来看生成singleton
的代理对象的 getSingletonInstance()
方法
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.
super.setFrozen(this.freezeProxy);
//使用ProxyFactory来生成需要的Proxy
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
//通过createAopProxy()返回的AopProxy来得到代理对象
protected Object getProxy(AopProxy aopProxy) {
return aopProxy.getProxy(this.proxyClassLoader);
}
getSingletonInstance()
方法首先读取了ProxyFactoryBean
中的配置,比如设置代理的方法的调用接口等,之后通过AopProxy
来具体生成代理对象;
AopProxy
是个接口类,他有两个实现类,一个是JdkDynamicAopProxy
还有一个是CglibAopProxy
,显然分别是通过JDK
和CGLIB
来实现需要的Proxy
代理对象
而AopProxy
的生成是通过createAopProxy()
方法拿到的,createAopProxy()
是基类ProxyCreatorSupprot
的方法,在文章的开头的类的继承关系中说过,ProxyCreatorSupprot
是AdvicedSupport
的子类,关于要生成什么样的代理对象的信息都是封装在AdvicedSupport
中
//ProxyCreatorSupprot
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
//通过AopProxyFactory取得AopProxy,这个AopProxyFactory是在初始化函数中定义的,使用的是DefaultAopProxyFactory
return getAopProxyFactory().createAopProxy(this);
}
这里使用了AopProxyFactory
创建AopProxy
,这个AopProxyFactory
是在初始化函数中定义的,使用的是DefaultAopProxyFactory
,我们看DefaultAopProxyFactory
可以看到,他作为AopProxy
对象的生产工厂,会先从AdvisedSupport
对象中取得配置的目标对象,再根据配置信息决定使用JDK
还是CGLIB
创建代理对象
@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.");
}
//如果targetClass是接口类,使用JDK生成Proxy
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
//CGLIB
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
对于使用JDK
生成AopProxy
,是在JdkDynamicAopProxy
中完成的
@Override
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//调用jdk生成Proxy
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
它首先从advised
对象中取得代理对象的代理接口配置,然后调用Proxy
的newProxyInstance
方法,最终得到对应的Proxy
对象,对于newProxyInstance
方法需要指明三个参数,类加载器,代理接口和Proxy
回调方法所在的对象,这个对象需要实现InvocationHandler
接口并实现invoke
方法,对于JdkDynamicAopProxy
来说,它本身就实现了InvocationHandler
和invoke
方法,所以这里直接传当前对象就行了
invoke
方法是代理对象进行拦截的回调入口,会作为回调函数被触发,通过invoke
方法的具体实现来完成对目标方法的调用的拦截和功能增强
在invoke
方法中把目标对象,拦截器链作为输入创建了ReflectiveMethodInvocation
对象完成对AOP
实现功能的封装
@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]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else 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.
//如果没有设置拦截器链则直接调用target对应的方法
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 {
//有拦截器链则需要拦截器之后才调用目标对象的相应方法,构造一个`ReflectiveMethodInvocation`对象完成对`AOP`实现功能的封装
// 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 != Object.class && 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);
}
}
}
在上面的方法中先获得了拦截器链
//拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
这个操作是由advised
对象完成的,这个advised
是一个AdvisedSupport
对象,我们可以看到getInterceptorsAndDynamicInterceptionAdvice
的实现
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
//使用了cache
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
//由advisorChainFactory完成拦截器链的生成
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
取得拦截器链是由advisorChainFactory
完成的,他是一个生成通知器链的工厂,在这里advisorChainFactory
被配置为一个DefaultAdvisorChainFactory
对象,在DefaultAdvisorChainFactory
中实现了拦截器链的获取过程:
@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.
//advisor链已经子啊config中持有了,这里直接使用
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)) {
//通过`AdvisorAdapterRegistry`对象实现拦截器的注册,他会对通知进行适配从而获得相应的拦截器
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;
}
可以看到,它会通过AdvisorAdapterRegistry
对象实现拦截器的注册,他会对通知进行适配从而获得相应的拦截器,这里是单件的GlobalAdvisorAdapterRegistry
,他的getIntercept
方法为AOP的实现做出了很大的贡献,这个方法封装着advice
织入实现的细节;
GlobalAdvisorAdapterRegistry
起到的基本上是一个适配器作用,设置了一系列的adapter
适配器,正是这些适配器的实现为Spring AOP
的advice
提供编织功能,先判断取得的advice
属于什么类型的advice
,从而通过不同的advice
类型注册不同的AdviceInterceptor
获得了拦截器链后,在invoke
方法中对拦截器链的调用都是通过在ReflectiveMethodInvocation
中通过proceed
方法实现的,在proceed
方法中,会逐个运行拦截器的拦截方法,在运行运行拦截器方法之前会对代理方法完成一个匹配判断,通过这个匹配判断是否满足切面的增强需求,如果满足则从拦截器中得到通知器,并启动通知器的invoke
方法进行切面增强
@Override
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 链处理
//获得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.
//对拦截器进行动态匹配判断 如果匹配则执行advice
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
//不匹配则递归调用proceed,直到所有的拦截器都被运行过为止
// 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);
}
}