- 浏览: 136937 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
西蜀石兰:
永远保持一颗好奇心,面对新鲜的事物时,乐意花代价去尝试一番,这 ...
优秀程序员必备的15大技能 -
liuwuhen:
代码还是不错的,头像确实有点
sprig AOP之ProxyFactory -
西蜀石兰:
这头像。。。。完全不用看代码了
sprig AOP之ProxyFactory -
coding1688:
...
你的知识资产 -
tao_gun:
...
你的知识资产
下面我们来看看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而言,其生产出来的对象是封装了目标对象的代理对象。
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而言,其生产出来的对象是封装了目标对象的代理对象。
发表评论
-
spring 事务
2012-08-21 15:38 971spring的事务是从TransactionProxyFact ... -
sprig AOP之ProxyFactory
2012-08-20 18:34 3676我们在项目中大多使用的声明式的AOP配置,其实在spring中 ... -
spring AOP源码分析之拦截器
2012-08-20 17:09 1376我们都知道在spring AOP中产生代理对象的方式有jdk和 ... -
spring jdbc 之一
2012-08-16 15:16 1361使用过jdbc的我们都知道spring jdbc ,首先我们看 ... -
spring jdbc 之二
2012-08-15 16:12 1523spring jdbcTemplate 提供了很多查询和更新功 ...
相关推荐
AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析...
死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理(csdn)————程序
哪怕没有看过源码的同学也应该知道,AOP是通过动态代理实现的,动态代理又分为两个部分:JDK动态代理和CGLIB动态代理 确实,Spring也就是通过这两种方式来实现AOP相关功能,下面就通过源码来简单求证下
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器...Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中
Java spring AOP源码
spring之AOP(动态代理),包括jdk动态代理和CGLib动态代理
主要对Spring AOP的相关概念和简单的静态代理、动态代理以及常见的几种AOP配置方式做总结学习。主要包括:1. AOP的常见概念 2. 静态代理 3. jdk动态代理 4. Aspectj and Aspectjweaver 5. **aop-config** 6. CGLIB ...
1.Spring入门和IOC介绍 2.对象依赖 3.AOP入门 4.JDBCTemplate和Spring事务 5.Spring事务原理 6.Spring事务的一个线程安全问题 7.IOC再回顾和面试题 8.AOP再回顾
Java流行框架源码分析:Spring源码、SpringBoot源码、SpringAOP源码、SpringSecurity源码、SpringSecurity OAuth2源码、JDK源码、Netty源码
Spring3.0.5支持AOP获取HttpServletResponse扩展资源:spring.web-3.0.5.jar和spring.webmvc-3.0.5.jar 是需要升级替换的。
Spring-Aop源码实现
一、适合人群 1、具备一定Java编程基础,初级开发者 ...(需要知道原理的请看spring aop源码,此处不做赘述) 3、可在现有源码上快速进行功能扩展 4、spring boot,mybatis,druid,spring aop的使用
spring aop 源码解析
NULL 博文链接:https://conkeyn.iteye.com/blog/2354644
Spring AOP源码笔记
spring aop spring aop spring aop spring aop spring aop spring aop spring aop spring aop spring aop
Spring源代码解析(五):Spring AOP获取Proxy Spring源代码解析(六):Spring声明式事务处理 Spring源代码解析(七):Spring AOP中对拦截器调用的实现 Spring源代码解析(八):Spring驱动Hibernate的实现 Spring源...
AOP的意思就是面向切面编程。本文主要是通过梳理JDK中自带的反射机制,实现 AOP动态代理模式,这也是Spring AOP 的实现原理
Spring AOP(面向切面编程)作为Spring框架的一个重要部分,为Java开发者提供了一个...通过对Spring AOP源码的深入分析,我们可以更好地理解其内部工作原理,从而在实际开发中更加灵活和高效地使用这一强大的编程范式。
Spring Aop 源码流程.doc