您的位置:首页 > 编程语言 > Java开发

Spring学习10-- AOP实现原理

2017-01-05 22:40 483 查看
AOP的原理不需要多讲,动态代理。那么,Spring在bean对象实例化的时候,是如何动态代理一个类的呢?又是如何完成方法织入的呢,来看一看源码。

1、AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforeInstantiation

翻开Spring学习08的内容,里面有讲到后置处理器BeanPostProcessor的实现原理,在给Bean实例化的过程中,调用了该类中的ceaterBean方法,里面有处理后置处理器的入口函数的调用

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
if (beanClass != null && !mergedBeanDefinition.isSynthetic()) {
//bean对象初始化之前的处理入口
Object bean = applyBeanPostProcessorsBeforeInstantiation(beanClass, beanName);
if (bean != null) {
//bean对象初始化之后的处理入口
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
return bean;
}
}


以applyBeanPostProcessorsAfterInitialization为例子,进入该方法

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//调用Bean实例所有的后置处理中的初始化后处理方法,为Bean实例对象在
//初始化之后做一些自定义的处理操作
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}


真正处理的方法是postProcessAfterInitialization,继续进去看看,AbstractAutowireCapableBeanFactory类中并没有实现这个方法,查看一下子类,真正实现的地方在AbstractAutoProxyCreator

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (isInfrastructureClass(bean.getClass(), beanName) || shouldSkip(bean.getClass(), beanName)) {
return bean;
}

// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
//创建代理
return createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
}

return bean;
}


真正创建代理的地方入口就在这里,进入createProxy

protected Object createProxy(
Class beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

// handle prototypes correctly
//获取所有的advisor, Advisor:充当Advice和Pointcut的适配器,类似使用Aspect的@Aspect注解的类(前一章节所//述)。一般有advice和pointcut属性
Advisor[] commonInterceptors = resolveInterceptorNames();

List allInterceptors = new ArrayList();
if (specificInterceptors != null) {
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors != null) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
if (logger.isDebugEnabled()) {
int nrOfCommonInterceptors = commonInterceptors != null ? commonInterceptors.length : 0;
int nrOfSpecificInterceptors = specificInterceptors != null ? specificInterceptors.length : 0;
logger.debug(
"Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
}

ProxyFactory proxyFactory = new ProxyFactory();
// Copy our properties (proxyTargetClass) inherited from ProxyConfig.
proxyFactory.copyFrom(this);

if (!isProxyTargetClass()) {
// Must allow for introductions; can't just set interfaces to
// the target's interfaces only.
Class[] targetsInterfaces = ClassUtils.getAllInterfacesForClass(beanClass);
for (int i = 0; i < targetsInterfaces.length; i++) {
proxyFactory.addInterface(targetsInterfaces[i]);
}
}

for (Iterator it = allInterceptors.iterator(); it.hasNext();) {
Advisor advisor = this.advisorAdapterRegistry.wrap(it.next());
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);

proxyFactory.setFrozen(this.freezeProxy);
//返回代理对象
return proxyFactory.getProxy();
}


正在返回代理的地方就是最后的getProxy()方法,进入,但是类中没有实现,在子类JdkDynamicAopProxy中有了实现

/**
* <ol>
* <li>获取代理类要实现的接口,除了Advised对象中配置的,还会加上SpringProxy, Advised(opaque=false)
* <li>检查上面得到的接口中有没有定义 equals或者hashcode的接口
* <li>调用Proxy.newProxyInstance创建代理对象
* </ol>
*/
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);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}


这样一个过程下来,一个代理对象就产生了,但是问题又来了,这个对象是如何工作的,也就是说,是如何织入的呢?

2、织入过程

上面说到类JdkDynamicAopProxy中geyProxy方法产生了一个代理对象,我们在动态代理中说过,动态代理最重要的地方就是实现InvocationHandler接口,其中invoke函数是代理生效的方法,正好,类JdkDynamicAopProxy就实现了这个接口,来找一下invoke方法,看里面做了写什么。

//AOP代理对象的回调方法
publicObject invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocationinvocation;
ObjectoldProxy = null;
booleansetProxyContext = false;
//获取通知的目标源
TargetSourcetargetSource = this.advised.targetSource;
ClasstargetClass = null;
Objecttarget = null;
try{
//如果代理目标对象的接口中没有定义equals()方法,且当前调用的方法
//是equals()方法,即目标对象没有自己实现equals()方法
if(!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
returnequals(args[0]);
}
//如果代理目标对象的接口中没有定义hashCode()方法,且当前调用的方法
//是hashCode()方法,即目标对象没有自己实现hashCode()方法
if(!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
returnhashCode();
}
//如果AOP配置了通知,使用反射机制调用通知的同名方法
if(!this.advised.opaque && method.getDeclaringClass().isInterface()&&                                method.getDeclaringClass().isAssignableFrom(Advised.class)){
returnAopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
ObjectretVal;
//如果当前通知暴露了代理,则将当前代理使用currentProxy()方法变为可用代理
if(this.advised.exposeProxy) {
oldProxy= AopContext.setCurrentProxy(proxy);
setProxyContext= true;
}
//获取目标对象
target= targetSource.getTarget();
if(target != null) {
targetClass= target.getClass();
}
//获取目标对象方法配置的拦截器(通知器)链
List<Object>chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,targetClass);
//如果没有配置任何通知
if(chain.isEmpty()) {
//没有配置通知,使用反射直接调用目标对象的方法,并获取方法返回值
retVal= AopUtils.invokeJoinpointUsingReflection(target, method, args);
}
//如果配置了通知
else{
//为目标对象创建方法回调对象,需要在调用通知之后才调用目标对象的方法
invocation= new ReflectiveMethodInvocation(proxy, target, method, args, targetClass,chain);
//调用通知链,沿着通知器链调用所有配置的通知
retVal= invocation.proceed();
}
//如果方法有返回值,则将代理对象最为方法返回
if(retVal != null && retVal == target &&method.getReturnType().isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())){
retVal= proxy;
}
returnretVal;
}
finally{
if(target != null && !targetSource.isStatic()) {
//释放目标对象
targetSource.releaseTarget(target);
}
if(setProxyContext) {
//存储代理对象
AopContext.setCurrentProxy(oldProxy);
}
}
}


过程如下:

1、Advised接口或者其父接口中定义的方法,直接反射调用,不应用通知

2、获取可以应用到此方法上的通知链(Interceptor Chain),如果有,则应用通知,并执行joinpoint; 如果没有,则直接反射执行joinpoint

获取通知链的过程getInterceptorsAndDynamicInterceptionAdvice,进入查看一下。这个方法在子类中实现。

public List getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Object proxy, Method method, Class targetClass) {

List cached = (List) this.methodCache.get(method);
if (cached == null) {
// recalculate
cached = AdvisorChainFactoryUtils.calculateInterceptorsAndDynamicInterceptionAdvice(
config, proxy, method, targetClass);
this.methodCache.put(method, cached);
}
return cached;
}


实际调用的是calculateInterceptorsAndDynamicInterceptionAdvice,进入查看

/**
* Return the static interceptors and dynamic interception advice that may apply
* to this method invocation.
* @return list of MethodInterceptor and InterceptionAdvice (if there's a dynamic
* method matcher that needs evaluation at runtime)
*/
public static List calculateInterceptorsAndDynamicInterceptionAdvice(
Advised config, Object proxy, 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 interceptorList = new ArrayList(config.getAdvisors().length);
boolean hasIntroductions = hasMatchingIntroductions(config,targetClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
for (int i = 0; i < config.getAdvisors().length; i++) {
Advisor advisor = config.getAdvisors()[i];
if (advisor instanceof PointcutAdvisor) {
// add it conditionally
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (methodMatches(mm,method, targetClass,hasIntroductions)) {
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (int j = 0; j < interceptors.length; j++) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher((MethodInterceptor) interceptors[j], mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (ia.getClassFilter().matches(targetClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
return interceptorList;
}


这个方法的作用就是

* 从提供的配置实例config中获取advisor列表,遍历处理这些advisor.如果是IntroductionAdvisor,

* 则判断此Advisor能否应用到目标类targetClass上.如果是PointcutAdvisor,则判断

* 此Advisor能否应用到目标方法method上.将满足条件的Advisor通过AdvisorAdaptor转化成Interceptor列表返回.

调用此方法获取目标对象方法配置的拦截器(通知器)链 。

返回上一层代码,查看一下拦截器链是怎么起作用的

JdkDynamicAopProxy 和CglibAopProxy创建AOPProxy代理对象,以及对目标对象的通知器回调我们了解到,当目标对象配置了通知器时,在对目标对象方法调用前首先需要回调通知器链,JdkDynamicAopProxy和CglibAopProxy都是通过将目标对象方法、方法参数、和通知器链、代理对象等封装为ReflectiveMethodInvocation类,然后通过ReflectiveMethodInvocation.proceed()方法调用通知器链

proceed方法源码如下

//通用通知器链
public Object proceed() throws Throwable {
//如果拦截器链中通知已经调用完毕
if(this.currentInterceptorIndex ==this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//这个方法调用AopUtils.invokeJoinpointUsingReflection方法,
//通过反射机制直接调用目标对象方法
returninvokeJoinpoint();
}
//获取拦截器链中的通知器或通知
ObjectinterceptorOrInterceptionAdvice=           this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//如果获取的通知器或通知是动态匹配方法拦截器类型
if(interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher){
//动态匹配方法拦截器
InterceptorAndDynamicMethodMatcherdm =
(InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
if(dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
//如果匹配,调用拦截器的方法
returndm.interceptor.invoke(this);
}
else{
//如果不匹配,递归调用proceed()方法,知道拦截器链被全部调用为止
returnproceed();
}
}
else{
//如果不是动态匹配方法拦截器,则切入点在构造对象之前进行静态匹配,调用
//拦截器的方法
return((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}


总结一下

1、AOP创建代理对象通过ProxyFactory创建的。

2、JdkDynamicAopProxy通过JDK提供的动态代理创建代理类,实现方式有两种一种是jdk的动态代理,如果没有实现接口,则使用CGLIB字节码技术生成代理类。

3、代理类创建通过invoke方法调用,主要是获取目标对象方法、方法参数、和通知器链、代理对象等。

4、将上述获取到的目标对象数据封装为ReflectiveMethodInvocation类,然后通过ReflectiveMethodInvocation.proceed()方法调用通知器链。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring