- 浏览: 91801 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
hvang1988:
...
Spring --- Transaction Management -
Branding:
谢谢,原来总是记不住,这下知道原理了
“Hello Java” -- Java安装
一)Spring AOP---schema-based approach
Spring AOP的配置方式,我强烈推荐这篇博客http://pandonix.iteye.com/blog/336873。作者对AOP的概念和Spring AOP的xml配置实现都做了清晰的介绍。我想我是不可能做更好的介绍了...这里就再作几点补充说明吧~~
二)动态代理
要说动态代理,就得先说静态代理。动静都是比较出来的嘛~~
静态代理:
UserDAOProxy和UserDAOImp一样,同样是UserDAO接口的实现,对于调用者而言,saveUser方法的使用完全相同,不同的是内部实现机制已经发生了一些变化――我们在UserDAOProxy中为UserDAO.saveUser方法套上了一个JTA事务管理的外壳。
很显然这样的结构设计,代理类只能代理某一个特定的接口(例子中是UserDAO接口)。现在假设系统中有20个类似的接口,针对每个接口实现一个Proxy,实在是个繁琐无味的苦力工程。所以我们需要一种设计能将接口也作为参数动态的传入,以实现对任意接口的动态代理!
动态代理
AOPFactory就是Spring最后实现动态代理的一个精简示意。getClassInstance()首先通过反射机制将配置文件中的String转换成响应的Object。而后txHandler.bind()将根据obj生成响应的动态代理返回。显然,动态代理的核心逻辑就在AOPHandler类中。下面让我们看看,它到底是如何实现的:
1'首先说说public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
参数说明:
ClassLoader loader:类加载器
Class<?>[] interfaces:得到全部的接口
InvocationHandler h:得到InvocationHandler接口的子类实例
注意:例子中InvocationHandler h传的是this。所以当获得动态代理后调用userDAO.saveUser时(假设我们的动态代理要代理的是userDAO接口),代理会调用AOPHandler.invoke来处理相应的逻辑。
此外newProxyInstance生产的动态代理类是无需我们手动编码参与的,程序会自动生成于内存中。这个自动生成的类就相当于上例静态代理中的UserDAOProxy,只是因为它在内存中我们看不见其源码罢了。
2'再说说,getIntercetors()。它严格来说和动态代理没什么关系。只是因为动态代理是接口名、接口内需要实现的方法名都不确定,所以在代理的前后处理时也不可避免的需要一些“动态”逻辑,需要采用反射机制。所以这里专门做了一些处理。和InvocationInfo 一样,具体的细节可以不关注。重点应该在AOPHandler本身。
3'介绍完了动态代理,我们可以发现一个结论:虽然动态代理的设计大大增加了代理的灵活型,但它仍然对被代理的类有一个限制:此类必须继承一个接口以供动态代理实现生成代理类!而CGLIB则进一步去除了这个限制
三)CGLIB
Spring中,引入了CGLib作为无接口情况下的动态代理实现。
CGLib与Dynamic Proxy的代理机制基本类似,只是其动态生成的代理对象并非某个接口的实现,而是针对目标类扩展的子类。
与Dynamic Proxy中的Proxy和InvocationHandler相对应,Enhancer和MethodInterceptor在CGLib中负责完成代理对象创建和方法截获处理。下面是通过CGLib进行动态代理的示例代码:
测试代码:
四)写好pointcut
对于pointcut的表达式,spring是参照AspectJ pointcut designators (PCD)的标准来做的。当然,由于AOP方面spring并没有AspectJ来得这么强大(spring只支持针对方法method的切面编程),所以在pointcut表达式上实际上也是取了PCD的一个子集而已。下面先说说PCD语法的几个关键字:
execution:(对符合条件的方法)执行AOP
within:在(满足条件的类型)内执行AOP (由于spring只支持方法层的AOP,所以spring中的within可以进一步解释为:对满足条件的类的方法执行AOP)
this:指动态代理类本身
target:指被动态代理类代理的对象(还是由于spring只支持方法层的AOP,而代理和被代理类的方法名肯定是一样的,所以spring中的this和target关键字几乎可以混用。)
args:对满足此参数条件的方法执行AOP
execution是spring最常用的表达式,下面我们详加说明:
此表达式的格式如下:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
modifiers-pattern:修饰符类型(public protect private)
ret-type-pattern:返回值类型
declaring-type-pattern:对象类型
name-pattern:方法名
parm-pattern:参数名
throws-pattern:异常
其中,除ret-type-pattern,name-pattern和parameters-pattern之外,其他都是可选的。比如:
execution(public * *(..)) 表示所有public的方法
execution(* set*(..)) 表示所有方法名以set开头的方法
execution(* com.xyz.service.AccountService.*(..)) 表示接口AccountService内的所有方法
execution(* com.spring.service.*.*(..)) 表示com.spring.service包下,返回值为任意类型;方法名任意;参数不作限制的所有方法。
execution(* com.xyz.service..*.*(..)) 表示com.xyz.service包及其子包下,返回值为任意类型;方法名任意;参数不作限制的所有方法。
再来说说within:
within(com.xyz.service.*) 表示com.xyz.service包下所有的joint point(spring的话就是指com.xyz.service包下所有的方法了)
within(com.xyz.service..*) 表示com.xyz.service包及其子包下所有的joint point(spring的话就是指com.xyz.service包及其子包下所有的方法了)
下面是this:
this(com.xyz.service.AccountService) 表示代理了接口com.xyz.service.AccountService的动态代理下的所有joint point
target:
target(com.xyz.service.AccountService) 表示接口com.xyz.service.AccountService下的所有joint point
args:
args(java.io.Serializable)表示对所有传入参数是java.io.Serializable的方法执行AOP
注:1'最后说一种spring特有的,唯一不在PCD范围内的表达式:bean(idOrNameOfBean)
bean(*Service) 对以Service结尾的bean执行AOP
2'Spring AOP所有的pointcut都是针对public方法的。对应proctect private的方法无法使用AOP. 如果需要对protect和private的方法进行AOP,可以使用Spring-driven native AspectJ weaving。
Spring AOP的配置方式,我强烈推荐这篇博客http://pandonix.iteye.com/blog/336873。作者对AOP的概念和Spring AOP的xml配置实现都做了清晰的介绍。我想我是不可能做更好的介绍了...这里就再作几点补充说明吧~~
二)动态代理
要说动态代理,就得先说静态代理。动静都是比较出来的嘛~~
静态代理:
public interface UserDAO { public void saveUser(User user); } public class UserDAOImp implements UserDAO{ public void saveUser(User user) { …… } } //静态代理。代理了接口UserDAO下的所有实现类,例如UserDAOImp public class UserDAOProxy implements UserDAO { private UserDAO userDAO; public UserDAOProxy(UserDAO userDAO) { this.userDAO = userDAO; } public void saveUser(User user) { UserTransaction tx = null; try { tx = (UserTransaction) (new InitialContext().lookup("java/tx")); userDAO.saveUser(user); tx.commit(); } catch (Exception ex) { if (null!=tx){ try { tx.rollback(); }catch(Exception e) { } } } } }
UserDAOProxy和UserDAOImp一样,同样是UserDAO接口的实现,对于调用者而言,saveUser方法的使用完全相同,不同的是内部实现机制已经发生了一些变化――我们在UserDAOProxy中为UserDAO.saveUser方法套上了一个JTA事务管理的外壳。
很显然这样的结构设计,代理类只能代理某一个特定的接口(例子中是UserDAO接口)。现在假设系统中有20个类似的接口,针对每个接口实现一个Proxy,实在是个繁琐无味的苦力工程。所以我们需要一种设计能将接口也作为参数动态的传入,以实现对任意接口的动态代理!
动态代理
public class AOPFactory { private static Log logger = LogFactory.getLog(AOPFactory.class); public static Object getClassInstance(String clzName){ Class cls; try { cls = Class.forName(clzName); return (Object)cls.newInstance(); } catch (Exception e) { logger.debug(e); throw new AOPRuntimeException(e); } } public static Object getAOPProxyedObject(String clzName){ AOPHandler txHandler = new AOPHandler(); Object obj = getClassInstance(clzName); return txHandler.bind(obj);//返回动态代理类!! } }
AOPFactory就是Spring最后实现动态代理的一个精简示意。getClassInstance()首先通过反射机制将配置文件中的String转换成响应的Object。而后txHandler.bind()将根据obj生成响应的动态代理返回。显然,动态代理的核心逻辑就在AOPHandler类中。下面让我们看看,它到底是如何实现的:
public class AOPHandler implements InvocationHandler { private static Log logger = LogFactory.getLog(AOPHandler.class); private List interceptors = null; private Object originalObject; public Object bind(Object obj) { this.originalObject = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); } /** * 在Invoke方法中,加载对应的Interceptor,并进行 * 预处理(before)、后处理(after)以及异常处理(exceptionThrow)过程 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; Throwable ex = null; InvocationInfo invInfo = new InvocationInfo(proxy, method, args,result, ex); logger.debug("Invoking Before Intercetpors!"); invokeInterceptorsBefore(invInfo); try { logger.debug("Invoking Proxy Method!"); result = method.invoke(originalObject, args); invInfo.setResult(result); logger.debug("Invoking After Method!"); invokeInterceptorsAfter(invInfo); } catch (Throwable tr) { invInfo.setException(tr); logger.debug("Invoking exceptionThrow Method!"); invokeInterceptorsExceptionThrow(invInfo); throw new AOPRuntimeException(tr); } return result; } private synchronized List getIntercetors() { if (null == interceptors) { interceptors = new ArrayList(); //Todo:读取配置,加载Interceptor实例 //interceptors.add(new MyInterceptor()); } return interceptors; } private void invokeInterceptorsBefore(InvocationInfo invInfo) { List interceptors = getIntercetors(); int len = interceptors.size(); for (int i = 0; i < len; i++) { ((Interceptor) interceptors.get(i)).before(invInfo); } } private void invokeInterceptorsAfter(InvocationInfo invInfo) { List interceptors = getIntercetors(); int len = interceptors.size(); for (int i = len - 1; i >= 0; i--) { ((Interceptor) interceptors.get(i)).after(invInfo); } } private void invokeInterceptorsExceptionThrow(InvocationInfo invInfo) { List interceptors = getIntercetors(); int len = interceptors.size(); for (int i = len - 1; i >= 0; i--) { ((Interceptor)interceptors.get(i)).exceptionThrow(invInfo); } } }
1'首先说说public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
参数说明:
ClassLoader loader:类加载器
Class<?>[] interfaces:得到全部的接口
InvocationHandler h:得到InvocationHandler接口的子类实例
注意:例子中InvocationHandler h传的是this。所以当获得动态代理后调用userDAO.saveUser时(假设我们的动态代理要代理的是userDAO接口),代理会调用AOPHandler.invoke来处理相应的逻辑。
此外newProxyInstance生产的动态代理类是无需我们手动编码参与的,程序会自动生成于内存中。这个自动生成的类就相当于上例静态代理中的UserDAOProxy,只是因为它在内存中我们看不见其源码罢了。
2'再说说,getIntercetors()。它严格来说和动态代理没什么关系。只是因为动态代理是接口名、接口内需要实现的方法名都不确定,所以在代理的前后处理时也不可避免的需要一些“动态”逻辑,需要采用反射机制。所以这里专门做了一些处理。和InvocationInfo 一样,具体的细节可以不关注。重点应该在AOPHandler本身。
3'介绍完了动态代理,我们可以发现一个结论:虽然动态代理的设计大大增加了代理的灵活型,但它仍然对被代理的类有一个限制:此类必须继承一个接口以供动态代理实现生成代理类!而CGLIB则进一步去除了这个限制
三)CGLIB
Spring中,引入了CGLib作为无接口情况下的动态代理实现。
CGLib与Dynamic Proxy的代理机制基本类似,只是其动态生成的代理对象并非某个接口的实现,而是针对目标类扩展的子类。
与Dynamic Proxy中的Proxy和InvocationHandler相对应,Enhancer和MethodInterceptor在CGLib中负责完成代理对象创建和方法截获处理。下面是通过CGLib进行动态代理的示例代码:
public class AOPInstrumenter implements MethodInterceptor { private static Log logger = LogFactory.getLog(AOPInstrumenter.class); private Enhancer enhancer = new Enhancer(); public Object getInstrumentedClass(Class clz) { enhancer.setSuperclass(clz); enhancer.setCallback(this); return enhancer.create(); } public Object intercept(Object o, Method method,Object[] methodParameters,MethodProxy methodProxy)throws Throwable { logger.debug("Before Method =>"+method.getName()); Object result = methodProxy.invokeSuper(o, methodParameters); logger.debug("After Method =>"+method.getName()); return result; } }
测试代码:
AOPInstrumenter aopInst = new AOPInstrumenter(); UserDAOImp userDAO = (UserDAOImp) aopInst.getInstrumentedClass(UserDAOImp.class); User user = new User(); user.setName("Erica"); userDAO.saveUser(user);
四)写好pointcut
对于pointcut的表达式,spring是参照AspectJ pointcut designators (PCD)的标准来做的。当然,由于AOP方面spring并没有AspectJ来得这么强大(spring只支持针对方法method的切面编程),所以在pointcut表达式上实际上也是取了PCD的一个子集而已。下面先说说PCD语法的几个关键字:
execution:(对符合条件的方法)执行AOP
within:在(满足条件的类型)内执行AOP (由于spring只支持方法层的AOP,所以spring中的within可以进一步解释为:对满足条件的类的方法执行AOP)
this:指动态代理类本身
target:指被动态代理类代理的对象(还是由于spring只支持方法层的AOP,而代理和被代理类的方法名肯定是一样的,所以spring中的this和target关键字几乎可以混用。)
args:对满足此参数条件的方法执行AOP
execution是spring最常用的表达式,下面我们详加说明:
此表达式的格式如下:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
modifiers-pattern:修饰符类型(public protect private)
ret-type-pattern:返回值类型
declaring-type-pattern:对象类型
name-pattern:方法名
parm-pattern:参数名
throws-pattern:异常
其中,除ret-type-pattern,name-pattern和parameters-pattern之外,其他都是可选的。比如:
execution(public * *(..)) 表示所有public的方法
execution(* set*(..)) 表示所有方法名以set开头的方法
execution(* com.xyz.service.AccountService.*(..)) 表示接口AccountService内的所有方法
execution(* com.spring.service.*.*(..)) 表示com.spring.service包下,返回值为任意类型;方法名任意;参数不作限制的所有方法。
execution(* com.xyz.service..*.*(..)) 表示com.xyz.service包及其子包下,返回值为任意类型;方法名任意;参数不作限制的所有方法。
再来说说within:
within(com.xyz.service.*) 表示com.xyz.service包下所有的joint point(spring的话就是指com.xyz.service包下所有的方法了)
within(com.xyz.service..*) 表示com.xyz.service包及其子包下所有的joint point(spring的话就是指com.xyz.service包及其子包下所有的方法了)
下面是this:
this(com.xyz.service.AccountService) 表示代理了接口com.xyz.service.AccountService的动态代理下的所有joint point
target:
target(com.xyz.service.AccountService) 表示接口com.xyz.service.AccountService下的所有joint point
args:
args(java.io.Serializable)表示对所有传入参数是java.io.Serializable的方法执行AOP
注:1'最后说一种spring特有的,唯一不在PCD范围内的表达式:bean(idOrNameOfBean)
bean(*Service) 对以Service结尾的bean执行AOP
2'Spring AOP所有的pointcut都是针对public方法的。对应proctect private的方法无法使用AOP. 如果需要对protect和private的方法进行AOP,可以使用Spring-driven native AspectJ weaving。
发表评论
-
Spring --- Transaction Management
2012-12-26 09:52 10694一)spring的事务管理 事务管理并非spring独 ... -
Spring --- AOP IV
2012-12-21 16:44 997Spring AOP APIs 一)一个最简单的例子 publ ... -
Spring --- AOP III
2012-12-19 13:19 1078这篇文章先补充两个AOP的概念: 一)引入(Introduct ... -
Spring --- AOP
2012-12-13 16:10 1196一)什么是AOP AOP(A ... -
Spring --- SpEL
2012-12-11 16:10 9613一)什么是SpEL SpEL -- Spring Expr ... -
Spring --- Data Binding
2012-12-10 14:40 3134一) BeanWrapper BeanWrapper这个类 ... -
Spring --- Validation
2012-12-07 15:05 1877一) Validator接口 Spring的Validat ... -
Spring --- Resource
2012-12-06 16:50 1594一)如何使用spring中的r ... -
Spring --- IOC III
2012-12-04 15:34 1325承接上两篇IOC的介绍,我们继续... 9)Applicati ... -
Spring --- IOC II
2012-11-30 15:43 1581承接前一篇Spring --- IOC,继续IOC的介绍 6 ... -
Spring --- IOC
2012-11-28 16:36 1149一) IOC其实很简单 什么是IOC(控制反转)? 这名 ... -
开篇简介--Spring is not only Spring Framework
2012-03-06 16:42 1765一)什么是Spring 在java领域,当我们提起Spri ...
相关推荐
spring-aop-1.1.1.jar spring-aop-1.2.6.jar spring-aop-1.2.9.jar spring-aop-2.0.2.jar spring-aop-2.0.6.jar spring-aop-2.0.7.jar spring-aop-2.0.8.jar spring-aop-2.0.jar spring-aop-2.5.1.jar spring-aop-...
开发工具 spring-aop-4.3.6.RELEASE开发工具 spring-aop-4.3.6.RELEASE开发工具 spring-aop-4.3.6.RELEASE开发工具 spring-aop-4.3.6.RELEASE开发工具 spring-aop-4.3.6.RELEASE开发工具 spring-aop-4.3.6.RELEASE...
赠送jar包:spring-aop-5.2.0.RELEASE.jar; 赠送原API文档:spring-aop-5.2.0.RELEASE-javadoc.jar; 赠送源代码:spring-aop-5.2.0.RELEASE-sources.jar; 赠送Maven依赖信息文件:spring-aop-5.2.0.RELEASE.pom;...
"spring-aop-jar"这个主题涉及到Spring框架中的核心组件之一——Spring AOP。这里我们将深入探讨Spring AOP、相关jar文件以及它们在实际开发中的作用。 首先,我们来看一下提供的文件: 1. aopalliance.jar:这是一...
赠送jar包:spring-aop-5.0.8.RELEASE.jar; 赠送原API文档:spring-aop-5.0.8.RELEASE-javadoc.jar; 赠送源代码:spring-aop-5.0.8.RELEASE-sources.jar; 赠送Maven依赖信息文件:spring-aop-5.0.8.RELEASE.pom;...
spring-aop-5.3.22.jar Spring AOP provides an Alliance-compliant aspect-oriented programming implementation allowing you to define method interceptors and pointcuts to cleanly decouple code that ...
赠送jar包:spring-aop-5.3.10.jar; 赠送原API文档:spring-aop-5.3.10-javadoc.jar; 赠送源代码:spring-aop-5.3.10-sources.jar; 赠送Maven依赖信息文件:spring-aop-5.3.10.pom; 包含翻译后的API文档:spring...
spring-aop-5.2.0.RELEASE
赠送jar包:spring-aop-5.0.10.RELEASE.jar; 赠送原API文档:spring-aop-5.0.10.RELEASE-javadoc.jar; 赠送源代码:spring-aop-5.0.10.RELEASE-sources.jar; 赠送Maven依赖信息文件:spring-aop-5.0.10.RELEASE....
赠送jar包:spring-aop-5.3.12.jar; 赠送原API文档:spring-aop-5.3.12-javadoc.jar; 赠送源代码:spring-aop-5.3.12-sources.jar; 赠送Maven依赖信息文件:spring-aop-5.3.12.pom; 包含翻译后的API文档:spring...
spring-aop-3.2.5.RELEASE.jar
赠送jar包:spring-aop-5.2.15.RELEASE.jar; 赠送原API文档:spring-aop-5.2.15.RELEASE-javadoc.jar; 赠送源代码:spring-aop-5.2.15.RELEASE-sources.jar; 赠送Maven依赖信息文件:spring-aop-5.2.15.RELEASE....
spring-aop-3.2.0.RELEASE.jar,一个Spring中AOP的jar包
spring-aop-6.0.2.jar
赠送jar包:spring-aop-4.3.20.RELEASE.jar; 赠送原API文档:spring-aop-4.3.20.RELEASE-javadoc.jar; 赠送源代码:spring-aop-4.3.20.RELEASE-sources.jar; 包含翻译后的API文档:spring-aop-4.3.20.RELEASE-...
赠送jar包:spring-aop-5.1.3.RELEASE.jar; 赠送原API文档:spring-aop-5.1.3.RELEASE-javadoc.jar; 赠送源代码:spring-aop-5.1.3.RELEASE-sources.jar; 赠送Maven依赖信息文件:spring-aop-5.1.3.RELEASE.pom;...
spring-aop-4.0.4.RELEASE 的jar包,亲测可用。。。。
spring-**core**-4.3.6.RELEASE.jar :包含spring框架基本的核心工具类,spring其他组件都要用到这个包里的类,其他组件的基本核心 spring-**beans**-4.3.6.RELEASE.jar:所有应用都要用到的jar包,它包含访问配置...
spring-aop-5.0.4.RELEASE.jar。
赠送jar包:spring-aop-4.3.20.RELEASE.jar 赠送原API文档:spring-aop-4.3.20.RELEASE-javadoc.jar 赠送源代码:spring-aop-4.3.20.RELEASE-sources.jar 包含翻译后的API文档:spring-aop-4.3.20.RELEASE-...