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而言,其生产出来的对象是封装了目标对象的代理对象。