spring AOP源码分析之获取代理对象

下面我们来看看Spring的AOP的一些相关代码是怎么得到Proxy的,让我们我们先看看AOP和SpringAOP的一些基本概念:

Advice:

通知,制定在连接点做什么,在Sping中,他主要描述Spring围绕方法调用注入的额外的行为,Spring提供的通知类型有:

beforeadvice,AfterReturningAdvice,ThrowAdvice,MethodBeforeAdvice,这些都是SpringAOP定义的接口类,具体的动作实现需要用户程序来完成。

Pointcut:

切点,其决定一个advice应该应用于哪个连接点,也就是需要插入额外处理的地方的集合,例如,被某个advice作为目标的一组方法。Springpointcut通常意味着标示方法,可以选择一组方法调用作为pointcut,Spring提供了具体的切点来给用户使用,比如正则表达式切点JdkRegexpMethodPointcut通过正则表达式对方法名进行匹配,其通过使用AbstractJdkRegexpMethodPointcut中的对MethodMatcher接口的实现来完成pointcut功能:

Java代码

publicfinalbooleanmatches(Methodmethod,ClasstargetClass){

//这里通过放射得到方法的全名

Stringpatt=method.getDeclaringClass().getName()+"."+method.getName();

for(inti=0;i<this.patterns.length;i++){

//这里是判断是否和方法名是否匹配的代码

booleanmatched=matches(patt,i);

if(matched){

for(intj=0;j<this.excludedPatterns.length;j++){

booleanexcluded=matchesExclusion(patt,j);

if(excluded){

returnfalse;

}

}

returntrue;

}

}

returnfalse;

}

publicfinalbooleanmatches(Methodmethod,ClasstargetClass){

//这里通过放射得到方法的全名

Stringpatt=method.getDeclaringClass().getName()+"."+method.getName();

for(inti=0;i<this.patterns.length;i++){

//这里是判断是否和方法名是否匹配的代码

booleanmatched=matches(patt,i);

if(matched){

for(intj=0;j<this.excludedPatterns.length;j++){

booleanexcluded=matchesExclusion(patt,j);

if(excluded){

returnfalse;

}

}

returntrue;

}

}

returnfalse;

}

在JDKRegexpMethodPointcut中通过JDK中的正则表达式匹配来完成pointcut的最终确定:

Java代码

protectedbooleanmatches(Stringpattern,intpatternIndex){

Matchermatcher=this.compiledPatterns[patternIndex].matcher(pattern);

returnmatcher.matches();

}

protectedbooleanmatches(Stringpattern,intpatternIndex){

Matchermatcher=this.compiledPatterns[patternIndex].matcher(pattern);

returnmatcher.matches();

}

Advisor:

当我们完成额外的动作设计(advice)和额外动作插入点的设计(pointcut)以后,我们需要一个对象把他们结合起来,这就是通知器-advisor,定义应该在哪里应用哪个通知。Advisor的实现有:DefaultPointcutAdvisor他有两个属性advice和pointcut来让我们配置advice和pointcut。

在ProxyFactoryBean中,它的AOP实现需要依赖JDK和GCLIB提供的Proxy特性,从FcatoryBean中获取对象,是用getObject()方法作为入口完成,让我们进入ProxyFactoryBean中获取对象,是用getObject()方法作为入口完成的;让我们进入ProxyFactoryBean的实现中去,这个我们一点也不陌生的getObject()方法,是FactoryBean需要实现的接口。对ProxyFactoryBean来说,把需要对target目标对象增加的增强处理,都通过getObject的实现代码

//获取对象

publicObjectgetObject()

throwsBeansException

{

//初始化通知其链

initializeAdvisorChain();

if(isSingleton())

//返回单例对象

returngetSingletonInstance();

if(targetName==null)

logger.warn("Usingnon-singletonproxieswithsingletontargetsisoftenundesirable.Enableprototypeproxiesbysettingthe'targetName'property.");

returnnewPrototypeInstance();

}

//对Advisor配置链的初始化

privatesynchronizedvoidinitializeAdvisorChain()

throwsAopConfigException,BeansException

{

if(advisorChainInitialized)

return;

if(!ObjectUtils.isEmpty(interceptorNames))

{

if(beanFactory==null)

thrownewIllegalStateException((newStringBuilder("NoBeanFactoryavailableanymore(probablyduetoserialization)-cannotresolveinterceptornames")).append(Arrays.asList(interceptorNames)).toString());

if(interceptorNames[interceptorNames.length-1].endsWith("*")&&targetName==null&&targetSource==EMPTY_TARGET_SOURCE)

thrownewAopConfigException("Targetrequiredafterglobals");

Stringas[];

intj=(as=interceptorNames).length;

for(inti=0;i<j;i++)

{

Stringname=as[i];

if(logger.isTraceEnabled())

logger.trace((newStringBuilder("Configuringadvisororadvice'")).append(name).append("'").toString());

if(name.endsWith("*"))

{

if(!(beanFactoryinstanceofListableBeanFactory))

thrownewAopConfigException("CanonlyuseglobaladvisorsorinterceptorswithaListableBeanFactory");

addGlobalAdvisor((ListableBeanFactory)beanFactory,name.substring(0,name.length()-"*".length()));

}else

{

Objectadvice;

if(singleton||beanFactory.isSingleton(name))

advice=beanFactory.getBean(name);

else

advice=newPrototypePlaceholderAdvisor(name);

addAdvisorOnChainCreation(advice,name);

}

}

}

advisorChainInitialized=true;

}

如果是生成singleton对象则在getSingleton中完成

privatesynchronizedObjectgetSingletonInstance()

{

if(singletonInstance==null)

{

targetSource=freshTargetSource();

if(autodetectInterfaces&&getProxiedInterfaces().length==0&&!isProxyTargetClass())

{

ClasstargetClass=getTargetClass();

if(targetClass==null)

thrownewFactoryBeanNotInitializedException("Cannotdeterminetargetclassforproxy");

//设置代理接口

setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass,proxyClassLoader));

}

super.setFrozen(freezeProxy);

singletonInstance=getProxy(createAopProxy());

}

returnsingletonInstance;

}

这里出现了AopProxy类型的对象是spring把AOP代理对象的实现与框架的其他部分有效的分离开,AopProxy是一个接口,它有两个子类实现

一个Cglib2AopProxy和JdkDynamicAopProxy,spring是通过CGLIB和JDK来生成需要的Proxy代理对象。

在ProxyCreatorSupport中的createAopProxy()方法

protectedfinalsynchronizedAopProxycreateAopProxy()

{

if(!active)

activate();

returngetAopProxyFactory().createAopProxy(this);

}

在DefaultAopProxyFactory中的createAopProxy()是通过通过工厂来产生代理对象

publicAopProxycreateAopProxy(AdvisedSupportconfig)

throwsAopConfigException

{

if(config.isOptimize()||config.isProxyTargetClass()||hasNoUserSuppliedProxyInterfaces(config))

{

ClasstargetClass=config.getTargetClass();

if(targetClass==null)

thrownewAopConfigException("TargetSourcecannotdeterminetargetclass:Eitheraninterfaceoratargetisrequiredforproxycreation.");

if(targetClass.isInterface())

returnnewJdkDynamicAopProxy(config);

if(!cglibAvailable)

thrownewAopConfigException("CannotproxytargetclassbecauseCGLIB2isnotavailable.AddCGLIBtotheclasspathorspecifyproxyinterfaces.");

else

//采用cglib方式产生代理对象

returnCglibProxyFactory.createCglibProxy(config);

}else

{

//采用jdk动态代理产生代理对象

returnnewJdkDynamicAopProxy(config);

}

}

protectedObjectgetProxy(AopProxyaopProxy)

{

returnaopProxy.getProxy(proxyClassLoader);

}

如果是CGlib方式,则产生代理对象,则在Cglib2AopProxy中的getProxy方法其源码如下:

publicObjectgetProxy(ClassLoaderclassLoader)

{

try

{

ClassrootClass=advised.getTargetClass();

Assert.state(rootClass!=null,"TargetclassmustbeavailableforcreatingaCGLIBproxy");

ClassproxySuperClass=rootClass;

if(AopUtils.isCglibProxyClass(rootClass))

{

proxySuperClass=rootClass.getSuperclass();

ClassadditionalInterfaces[]=rootClass.getInterfaces();

Classaclass[];

intj=(aclass=additionalInterfaces).length;

for(inti=0;i<j;i++)

{

ClassadditionalInterface=aclass[i];

advised.addInterface(additionalInterface);

}

}

validateClassIfNecessary(proxySuperClass);

Enhancerenhancer=createEnhancer();

if(classLoader!=null)

{

enhancer.setClassLoader(classLoader);

if((classLoaderinstanceofSmartClassLoader)&&((SmartClassLoader)classLoader).isClassReloadable(proxySuperClass))

enhancer.setUseCache(false);

}

enhancer.setSuperclass(proxySuperClass);

enhancer.setStrategy(newUndeclaredThrowableStrategy(java/lang/reflect/UndeclaredThrowableException));

enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(advised));

enhancer.setInterceptDuringConstruction(false);

Callbackcallbacks[]=getCallbacks(rootClass);

enhancer.setCallbacks(callbacks);

enhancer.setCallbackFilter(newProxyCallbackFilter(advised.getConfigurationOnlyCopy(),fixedInterceptorMap,fixedInterceptorOffset));

Classtypes[]=newClass[callbacks.length];

for(intx=0;x<types.length;x++)

types[x]=callbacks[x].getClass();

enhancer.setCallbackTypes(types);

Objectproxy;

if(constructorArgs!=null)

proxy=enhancer.create(constructorArgTypes,constructorArgs);

else

proxy=enhancer.create();

returnproxy;

}

catch(Exceptionex)

{

thrownewAopConfigException("UnexpectedAOPexception",ex);

}

}

我们在来看下JdkDynamicAopProxy实现了InvokeHandle和Aopproxy接口jdk的代理方式。

publicObjectgetProxy(ClassLoaderclassLoader)

{

if(logger.isDebugEnabled())

logger.debug((newStringBuilder("CreatingJDKdynamicproxy:targetsourceis")).append(advised.getTargetSource()).toString());

ClassproxiedInterfaces[]=AopProxyUtils.completeProxiedInterfaces(advised);

findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);

//这是jdk的代理方式,将执行invoke方法

returnProxy.newProxyInstance(classLoader,proxiedInterfaces,this);

}

这样用Proxy包装target之后,通过ProxyFactoryBean得到对其方法的调用就被Proxy拦截了,ProxyFactoryBean的getObject()方法得到的实际上是一个Proxy了,我们的target对象已经被封装了。对ProxyFactoryBean这个工厂bean而言,其生产出来的对象是封装了目标对象的代理对象。

相关推荐