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);
}
}