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

下面我们来看看Spring的AOP的一些相关代码是怎么得到Proxy的,让我们我们先看看AOP和Spring AOP的一些基本概念:
Advice:
通知,制定在连接点做什么,在Sping中,他主要描述Spring围绕方法调用注入的额外的行为,Spring提供的通知类型有:
before advice,AfterReturningAdvice,ThrowAdvice,MethodBeforeAdvice,这些都是Spring AOP定义的接口类,具体的动作实现需要用户程序来完成。
Pointcut:
切点,其决定一个advice应该应用于哪个连接点,也就是需要插入额外处理的地方的集合,例如,被某个advice作为目标的一组方法。Spring pointcut通常意味着标示方法,可以选择一组方法调用作为pointcut,Spring提供了具体的切点来给用户使用,比如正则表达式切点 JdkRegexpMethodPointcut通过正则表达式对方法名进行匹配,其通过使用 AbstractJdkRegexpMethodPointcut中的对MethodMatcher接口的实现来完成pointcut功能:
Java代码
public final boolean matches(Method method, Class targetClass) {
//这里通过放射得到方法的全名
String patt = method.getDeclaringClass().getName() + "." + method.getName();
for (int i = 0; i < this.patterns.length; i++) {
// 这里是判断是否和方法名是否匹配的代码
boolean matched = matches(patt, i);
if (matched) {
for (int j = 0; j < this.excludedPatterns.length; j++) {
boolean excluded = matchesExclusion(patt, j);
if(excluded) {
return false;
}
}
return true;
}
}
return false;
}

public final boolean matches(Method method, Class targetClass) {
//这里通过放射得到方法的全名
String patt = method.getDeclaringClass().getName() + "." + method.getName();
for (int i = 0; i < this.patterns.length; i++) {
// 这里是判断是否和方法名是否匹配的代码
boolean matched = matches(patt, i);
if (matched) {
for (int j = 0; j < this.excludedPatterns.length; j++) {
boolean excluded = matchesExclusion(patt, j);
if(excluded) {
return false;
}
}
return true;
}
}
return false;
}

在JDKRegexpMethodPointcut中通过JDK中的正则表达式匹配来完成pointcut的最终确定:
Java代码
protected boolean matches(String pattern, int patternIndex) {
Matcher matcher = this.compiledPatterns[patternIndex].matcher(pattern);
return matcher.matches();
}

protected boolean matches(String pattern, int patternIndex) {
Matcher matcher = this.compiledPatterns[patternIndex].matcher(pattern);
return matcher.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的实现代码

//获取对象
public Object getObject()
throws BeansException
{
//初始化通知其链
initializeAdvisorChain();
if(isSingleton())
//返回单例对象
return getSingletonInstance();
if(targetName == null)
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the 'targetName' property.");
return newPrototypeInstance();
}

//对Advisor配置链的初始化

private synchronized void initializeAdvisorChain()
throws AopConfigException, BeansException
{
if(advisorChainInitialized)
return;
if(!ObjectUtils.isEmpty(interceptorNames))
{
if(beanFactory == null)
throw new IllegalStateException((new StringBuilder("No BeanFactory available anymore (probably due to serialization) - cannot resolve interceptor names ")).append(Arrays.asList(interceptorNames)).toString());
if(interceptorNames[interceptorNames.length - 1].endsWith("*") && targetName == null && targetSource == EMPTY_TARGET_SOURCE)
throw new AopConfigException("Target required after globals");
String as[];
int j = (as = interceptorNames).length;
for(int i = 0; i < j; i++)
{
String name = as[i];
if(logger.isTraceEnabled())
logger.trace((new StringBuilder("Configuring advisor or advice '")).append(name).append("'").toString());
if(name.endsWith("*"))
{
if(!(beanFactory instanceof ListableBeanFactory))
throw new AopConfigException("Can only use global advisors or interceptors with a ListableBeanFactory");
addGlobalAdvisor((ListableBeanFactory)beanFactory, name.substring(0, name.length() - "*".length()));
} else
{
Object advice;
if(singleton || beanFactory.isSingleton(name))
advice = beanFactory.getBean(name);
else
advice = new PrototypePlaceholderAdvisor(name);
addAdvisorOnChainCreation(advice, name);
}
}

}
advisorChainInitialized = true;
}


如果是生成singleton对象则在getSingleton中完成
private synchronized Object getSingletonInstance()
{
if(singletonInstance == null)
{
targetSource = freshTargetSource();
if(autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass())
{
Class targetClass = getTargetClass();
if(targetClass == null)
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
//设置代理接口
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, proxyClassLoader));
}
super.setFrozen(freezeProxy);
singletonInstance = getProxy(createAopProxy());
}
return singletonInstance;
}
这里出现了AopProxy类型的对象是spring把AOP代理对象的实现与框架的其他部分有效的分离开,AopProxy是一个接口,它有两个子类实现
一个Cglib2AopProxy和JdkDynamicAopProxy,spring 是通过CGLIB和JDK来生成需要的Proxy代理对象。

在ProxyCreatorSupport 中的 createAopProxy()方法
protected final synchronized AopProxy createAopProxy()
{
if(!active)
activate();

return getAopProxyFactory().createAopProxy(this);
}

在 DefaultAopProxyFactory 中的 createAopProxy()是通过通过工厂来产生代理对象
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.");
if(targetClass.isInterface())
return new JdkDynamicAopProxy(config);
if(!cglibAvailable)
throw new AopConfigException("Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.");
else
//采用cglib方式产生代理对象
return CglibProxyFactory.createCglibProxy(config);
} else
{
//采用jdk动态代理产生代理对象
return new JdkDynamicAopProxy(config);
}
}


protected Object getProxy(AopProxy aopProxy)
{
return aopProxy.getProxy(proxyClassLoader);
}

如果是CGlib方式,则产生代理对象,则在Cglib2AopProxy中的getProxy方法其源码如下:
public Object getProxy(ClassLoader classLoader)
{
try
{
Class rootClass = advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class proxySuperClass = rootClass;
if(AopUtils.isCglibProxyClass(rootClass))
{
proxySuperClass = rootClass.getSuperclass();
Class additionalInterfaces[] = rootClass.getInterfaces();
Class aclass[];
int j = (aclass = additionalInterfaces).length;
for(int i = 0; i < j; i++)
{
Class additionalInterface = aclass[i];
advised.addInterface(additionalInterface);
}
}
validateClassIfNecessary(proxySuperClass);
Enhancer enhancer = createEnhancer();
if(classLoader != null)
{
enhancer.setClassLoader(classLoader);
if((classLoader instanceof SmartClassLoader) && ((SmartClassLoader)classLoader).isClassReloadable(proxySuperClass))
enhancer.setUseCache(false);
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setStrategy(new UndeclaredThrowableStrategy(java/lang/reflect/UndeclaredThrowableException));
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(advised));
enhancer.setInterceptDuringConstruction(false);
Callback callbacks[] = getCallbacks(rootClass);
enhancer.setCallbacks(callbacks);
enhancer.setCallbackFilter(new ProxyCallbackFilter(advised.getConfigurationOnlyCopy(), fixedInterceptorMap, fixedInterceptorOffset));
Class types[] = new Class[callbacks.length];
for(int x = 0; x < types.length; x++)
types[x] = callbacks[x].getClass();

enhancer.setCallbackTypes(types);
Object proxy;
if(constructorArgs != null)
proxy = enhancer.create(constructorArgTypes, constructorArgs);
else
proxy = enhancer.create();
return proxy;
}
catch(Exception ex)
{
throw new AopConfigException("Unexpected AOP exception", ex);
}
}


我们在来看下JdkDynamicAopProxy 实现了InvokeHandle和Aopproxy接口jdk的代理方式。
public Object getProxy(ClassLoader classLoader)
{
if(logger.isDebugEnabled())
logger.debug((new StringBuilder("Creating JDK dynamic proxy: target source is ")).append(advised.getTargetSource()).toString());
Class proxiedInterfaces[] = AopProxyUtils.completeProxiedInterfaces(advised);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//这是jdk的代理方式,将执行invoke方法
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

这样用Proxy包装target之后,通过ProxyFactoryBean得到对其方法的调用就被Proxy拦截了, ProxyFactoryBean的getObject()方法得到的实际上是一个Proxy了,我们的target对象已经被封装了。对 ProxyFactoryBean这个工厂bean而言,其生产出来的对象是封装了目标对象的代理对象。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值