Spring中的AOP
Posted mthoutai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring中的AOP相关的知识,希望对你有一定的参考价值。
在上一篇博客中,我们讲了Spring的IOC,以下,我们继续解说Spring的还有一个核心AOP
AOP:
在软件业,AOP为Aspect Oriented Programming的缩写。意为:面向切面编程,通过预编译方式和执行期动态代理实现程序功能的统一维护的一种技术。
AOP也是Action Oriented Programming 的缩写,意为:面向切面编程,是函数式编程的一种衍生范型。AOP在其它领域也有其它含义。
AOP的具体解释:
还是老规矩,站在巨人的肩膀上,看看其它人对AOP的理解:
动态代理——JDK和CGlib
为什么须要CGlib
以上两个样例都是应用JDK动态代理实现的AOP。可是,我们知道Spring给我们提供了两种实现代理的方式,一种是JDK的动态代理。另一种是CGlib的动态代理。那么。为什么要提供CGlib代理呢?
使用JDK创建代理有一个限制,即它仅仅能为接口创建代理实例,这一点我们可从Proxy的接口newProxyInstance(CIassLoader loader,Class[] interfaces。InvocationHandIer h)的方法签名中就看得非常清楚:第二个入參interfaces就是须要代理实例实现的接口列表。
尽管而向接口编程的思想被非常多大师级人物(包含RodJohnson)推崇,但在实际开发中,很多开发人员也对此深感困惑:难道对一个简单业务表的操作也须要老老实实地创建5个类(领域对象类、Dao接口。Dao实现类,Service接口和service实现类)吗?难道不能直接通过实现类构建程序吗?对于这个问题。我们非常难给出一个孰好孰劣的准确推断,但我们确实发现有非常多不使用接口的项目也取得了非常好的效果(包含大家所熟悉的SpringSide开源项目)。
对于没有通过接口定义业务方法的类,怎样动态创建代理实例呢?JDK的代理技术显然己经黔驴技穷。CGLib作为一个替代者,填补了这个空缺。
CGLib实现动态代理
CGLib採用很底层的字节码技术,能够为一个类创建子类。并在子类中採用方法拦截的技术拦截全部父类方法的调用,并顺势织入横切逻辑。
由于和JDK动态代理原理一样,所以这里简单的写一下代理类的实现:
packagecom.proxy.spring; importjava.lang.reflect.Method; importnet.sf.cglib.proxy.Enhancer; importnet.sf.cglib.proxy.MethodInterceptor; importnet.sf.cglib.proxy.MethodProxy; publicclass CglibProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); public Object getProxy(Class clazz){ enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object obj, Methodmethod, Object[] args, MethodProxy proxy) throws Throwable{ System.out.println(obj.getClass().getName()+"."+method.getName()); Objectresulet=proxy.invokeSuper(obj,args); System.out.println("========end==================="); return resulet; } }
JDK和CGlib的差异:
JDK和CGlib除了在是否使用接口上的差异以外,在性能上也有一定的差异,理解这些差异,能够让我们更好的使用它们:
JDK动态代理所创建的代理对象,在JDK1.3下,性能强差人意。尽管在高版本号的JDK中。动态代理对象的性能得到了非常大的提高,可是有研究表明,CGLib所创建的动态代理对象的性能依然比JDK的所创建的代理对象的性能高不少(大概10倍)。但CGLib在创建代理对象时所花费的时间却比JDK动态代理多(大概8倍),所以对于singleton的代理对象或者具有实例池的代理由于无须频繁创建代理对象,所以比較适合用CGLib动态代理技术。反之适合用JDK动态代理技术,值得一提的是。由于CGLib採用动态创建子类的方式生成代理对象。所以不能对目标类中的final,private等方法进行代理。
Spring中的AOP
JDK和CGlib的一些缺陷
可是。以上我们说来说去,一直在说动态代理,尽管动态代理实现了AOP,可是,我们想一下我们实际的应用,就会发现有非常多问题,当然。Spring AOP就是基础这些问题创建的:
1)目标类的全部方法都加入了性能监视横切逻辑,而有时,这并非我们所期望的。我们可能仅仅希望对业务类中的某些特定方法加入横切逻辑;
2)我们通过硬编码的方式指定了织入横切逻辑的织入点。即在目标类业务方法的開始和结東前织入代码;
3)我们手工编写代理实例的创建过程,为不同类创建代理时。须要分别编写对应的程序代码,无法做到通用。
Spring的解决方式
以上三个问题,在AOP中占用重要的地位。由于SpringAOP的主要工作就是环绕以上三点展开。SpringAOP通过Pointcut(切点)指定在哪些类的哪些方法上织入横切逻辑。通过Advice(增强)描写叙述横切逻辑和方法的详细织入点(方法前、方法后、方法的两端等)。此外,Spring通过Advisor(切面)将Pointcut和Advice两者组装起来。有了Advisor的信息,Spring就能够利用JDK或CGLib的动态代理技术採用统一的方式为目标Bean创建织入切面的代理对象了。
Spring中的AOP与IOC
在Spring容器里。我们能够发现,Spring容器包括各种增强类,比方前置增强,后置增强,围绕增强等,还有各种切点。切面。以解决上述动态代理所存在的一些问题,事实上怎样解决这些问题我们暂且不研究(研究起来可能就不是一篇博客能够写得完的了),总之,Spring已经把这些类都已经写好了,如今要使用这些东西。比方我们须要在一个add方法前面插入验证,那么我们应该怎么做呢?假设我们没有接触过Spring,一定会这样想,那就在和之前使用JDK或者CGlib动态代理一样直接调用不就好了吗:
MyProxy hander = new MyProxy(); Animal dog = (Animal)hander.createProxyInstance(new Dog()); dog.run(); dog.jump();
这里我们非常easy发现,代理已经和被代理的类耦合在一起了。这里我们就发现。我们伟大的IOC就须要出现来了,我们仅仅须要把他们交给第三方来实现解耦合就能够了。
IOC和AOP怎样是Spring变得强大
事实上,最后这段话是我之前一直都没有想过的。由于之前一直在强调Spring的核心是IOC和AOP,仅仅是在想IOC是什么?AOP是什么?从来没有把他们关联起来想,事实上。从这里我们就能够看出。Spring的AOP事实上是构建于IOC之上,和IoC浑然天成统一于Spring的容器之中,也就是说,假设没有Spring IOC,AOP是无法发挥他的强大的作用的。当然,假设没有Spring AOP。IOC还是有非常多问题无法解决。同一时候,我们在想一下Spring的其它技术,比方事务,我们应该对事务比較清楚,Spring的事务就是被AOP到Spring中的。当然。还有比方对照方JDBC、Hibernate等的集成事实上都是在Spring IOC的基础上开花结果的。事实上假设这样想下去。Spring的学习,就变成使用IOC或者AOP对已经存在的类的整合,随便什么类,反正拿过来控制依赖注入一下。或者是当切进去就能够为我们所用了。假设从这个角度看Spring。是不是就发现Spring变得简单而强大了!
以上是关于Spring中的AOP的主要内容,如果未能解决你的问题,请参考以下文章