菜鸟级Spring AOP开发简介
2015-11-15 16:44
489 查看
最近用到了AOP编程,由于之前对这方面一直稀里糊涂的,所以打算写这篇文章来巩固一下自己的知识。
4000
:
静态AOP:在编译时期实现AOP,将切面直接以字节码形式编译到目标字节码文件中,这样对系统的性能没有影响,但是不是非常的灵活,程序是写死的。
动态AOP:在程序运行时期,所有的类加载器加载字节码前,对其进行拦截,将切面插入,利用的是动态代理的原理,底层java反射。
下面只介绍基于Spring注解方式实现AOP编程。
4.Spring实现AOP的例子
首先,我们创建一个普通类,假设该类为我们的业务逻辑类,吃饭
然后,编写我们的切面类用于在我们的业务逻辑类执行前后添加一些方法。
这里@Aspect表示被其注解的类为一个切面,我们只需在spring配置文件中添加 来支持对切面注解的自动扫描。
在spring中,有五类advice:
@Before:在所拦截方法执行之前执行一段逻辑。
@After:在所拦截方法执行之后执行一段逻辑。
@AftertReturning:在所拦截方法执行并有返回值之后执行一段逻辑,与其它通知不同的是,该通知方法可以获取返回值。
@AfterThrowing:在所拦截方法抛出异常后执行一段逻辑。
@Around:可以同时在所拦截方法的前后执行一段逻辑。
在上述例子中主要讲解了@Before与@After两种方式。
下面说一下我们的表达式,也就是切入点execution。
第一个*表示返回值为任意类型
com.mjl.Util.eat.eat表示com.mjl.Util包中的eat类中的eat方法,当然也可以写成com.mjl.Util.eat.*,表示eat类中的所有方法。或者为com.mjl.Util.. 表示Util包中的所有方法都为切入点。
(..)表示参数。
当然其中还有很多种写法,非常复杂,我就具体就不一一介绍了。
在spring配置文件中进行以下配置
编写测试类
结果如下图所示,AOP执行成功,当然这只是一个最简单的例子,AOP能够完成的功能非常多。
1.什么是AOP?
AOP是Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。 在大型程序中,有许多重复的,不可少的功能,如日志记录、权限检查等功能,它们散落在我们程序的各个角落,如果我们有一天对这些功能的接口进行了修改,那么很有可能会程序中的许多地方都会进行相应的修改,这是一个工程量很大的事情并且这样做容易出问题,一部留神哪里就忘了改或者改错。所以,AOP编程就是将这些程序中的公共类功能提取出来,做成一个切面,插入到我们的程序中,这样做的好处在于: 1.代码可以重用,我们不用在需要插入相应功能的地方一个个的编写代码,只需使用注解插入就行。 2.低侵入式,有没有这部分代码对原有的功能没有损害,底层是使用动态代理机制。 具体的介绍可以找往上的文章,有很多文章介绍的很清楚。
2.AOP的一些概念
1.Aspect(切面):网上解释的都不是很清楚,我个人认为是一个系统功能的实现,比如日志切面、事务切面、性能分析切面等,就是用来存放我们这个方法的一个Java类。 2.Joinpoint(连接点):是指切面要切入的地方,比如某个方法的名称。 3.Pointcut(切入点):切入点是一系列连接点的集合,因为连接点在系统中有成千上万个,所以要定义一个切入点,切入点在实现过程中是使用execution表达式来声明来指定。 4.advice(通知):指的是切面的具体实现时间,共有前置通知(Before)、后置通知(AfterReturning)、异常通知(AfterThrowing)、最终通知(After)与环绕通知(Around)5种。 5.织入(Weaving): 将我们的切面应用插入到我们需要插入的应用的过程。
3.Spring实现AOP的方式
实现AOP共有两种方式,分别为静态AOP与动态AOP4000
:
静态AOP:在编译时期实现AOP,将切面直接以字节码形式编译到目标字节码文件中,这样对系统的性能没有影响,但是不是非常的灵活,程序是写死的。
动态AOP:在程序运行时期,所有的类加载器加载字节码前,对其进行拦截,将切面插入,利用的是动态代理的原理,底层java反射。
下面只介绍基于Spring注解方式实现AOP编程。
4.Spring实现AOP的例子
首先,我们创建一个普通类,假设该类为我们的业务逻辑类,吃饭
/** * Created by Alvin on 15/11/15. */ public class eat { public void eat(){ System.out.println("我在吃饭"); } }
然后,编写我们的切面类用于在我们的业务逻辑类执行前后添加一些方法。
/** * Created by Alvin on 15/11/15. */ @Aspect public class eatAOP { @Before("execution(* com.mjl.Util.eat.eat(..))") public void beforeEat(JoinPoint jp){ System.out.println("吃饭前洗手"); } @After("execution(* com.mjl.Util.eat.eat(..))") public void afterEat(JoinPoint jp){ System.out.println("吃完饭洗碗"); } }
这里@Aspect表示被其注解的类为一个切面,我们只需在spring配置文件中添加 来支持对切面注解的自动扫描。
在spring中,有五类advice:
@Before:在所拦截方法执行之前执行一段逻辑。
@After:在所拦截方法执行之后执行一段逻辑。
@AftertReturning:在所拦截方法执行并有返回值之后执行一段逻辑,与其它通知不同的是,该通知方法可以获取返回值。
@AfterThrowing:在所拦截方法抛出异常后执行一段逻辑。
@Around:可以同时在所拦截方法的前后执行一段逻辑。
在上述例子中主要讲解了@Before与@After两种方式。
下面说一下我们的表达式,也就是切入点execution。
* com.mjl.Util.eat.eat(..)
第一个*表示返回值为任意类型
com.mjl.Util.eat.eat表示com.mjl.Util包中的eat类中的eat方法,当然也可以写成com.mjl.Util.eat.*,表示eat类中的所有方法。或者为com.mjl.Util.. 表示Util包中的所有方法都为切入点。
(..)表示参数。
当然其中还有很多种写法,非常复杂,我就具体就不一一介绍了。
在spring配置文件中进行以下配置
<aop:aspectj-autoproxy proxy-target-class="true" /> <bean id="eat" class="com.mjl.Util.eat"></bean> <bean id="eatAOP" class="com.mjl.aop.eatAOP"/>
编写测试类
/** * Created by Alvin on 15/11/15. */ public class testEatAOP { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); eat e = (eat) ac.getBean("eat"); @Test public void testEatAOP(){ e.eat(); } }
结果如下图所示,AOP执行成功,当然这只是一个最简单的例子,AOP能够完成的功能非常多。