AOP是面向切面编程,Aop的主要作用就是可以动态的向运行程序中插入代码段。Aop的最主要作用就是日志文件的编写。Aop的底层思想就是动态代理,而动态代理运用了Java底层的反射机制。动态代理用代理对象代替原始对象。在JDK原始动态代理中有一个缺陷就是他们一定要实现同一个接口,如果原始对象没有实现接口就无法使用动态代理。Aop的主要对象就是切面,使用Aop可以使业务模块更加简洁、日志代码集中便于维护管理。
目前Spring使用的Aop框架是AspectJ,它既可以支持注解模式添加Aop也支持利用配置XMl的方式添加Aop。一般比较重要的业务代码建议用配置xml的方式添加,普通业务代码可以使用注解模式添加更加方便。在Spring中使用Aop一个是使用了jdk原生的动态代理(需要实现接口)另一个就是使用了cglib(无需实现接口)。但要在Spring中使用Aop总的步骤如下:
1.需要导入jar包
commons-logging-1.1.3.jar spring-aop-4.0.0.RELEASE.jar spring-beans-4.0.0.RELEASE.jar spring-context-4.0.0.RELEASE.jar spring-core-4.0.0.RELEASE.jar spring-expression-4.0.0.RELEASE.jar spring-aspects-4.0.0.RELEASE.jar 以及强化版AOP 即没有实现同一接口也可以实现AOP com.springsource.net.sf.cglib-2.2.0.jar com.springsource.org.aopalliance-1.0.0.jar com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
2.需要引入aop名称空间
3.在xml文件中写下配置语句<aop:aspectj-autoproxy>
4.在IOC容器中配置需要添加Aop的bean实例
5.在切面类上添加@Aspect注解和五大通知注解或Xml配置切面和五大通知
@Before:在方法执行前通知
@After:在方法执行之后通知
@AfterReturning:返回通知,在方法返回后执行
@AfterThrowing:在方法抛出异常后执行
@Around(最强大的功能,相当于直接执行了动态代理):围绕方法执行
6.为以上五个通知注解配置切入点,配置切入点后,Aop就会在切入点方法执行前后执行!
切入点编写之通配符:
1. * 匹配一个或者多个字符和一个参数但只能配置一层路径! 2. ..任意多个参数,匹配任意多个路径 3. &&和||与日常代码使用相同
切入点编写之返回值:
returning=""(正常返回的结果) throwing="" (执行异常时返回异常信息)
切入点示例:
@AfterReturning(value="execution(public String com.AopTest..MyMethod*.*(..))",returning="name") public static void ReturnAlert(JoinPoint joinPoint,Object name) //如果不希望每次都填写切入点可以使用@Pointcut注解,即可重复使用切入点。 //该切入点访问权限值为public,返回值类型为String,Com.MyAopTest.后缀.Mymethod下的所有任意参数的任意方法!执行成功的返回值是name。 //注意JoinPoint是Aop方法对象,里面封装了Aop切面的信息,其中最重要的是Signature signature=jointPoint.getSignature();用来获取方法信息。 //其他还有JointPoint.getArgs[]获取方法参数, //jointPoint.getTarget();获取被代理对象 //jointPoint.getThis();获取代理对象
<bean id="Mymethod" class="com.AopTest.MyMethod"></bean> <bean id="AopMethod" class="com.logs.MyMethod"></bean> <!--将切面和需要执行切面的类加入IOC容器--> <aop:config> <aop:pointcut expression="execution(public String com.AopTest..MyMethod*.*(..))" id="AllPoint"/> <!-- 配置pointcut--> <aop:aspect ref="AopMethod"> <aop:around method="Aroundlog" pointcut-ref="AllPoint"/> <aop:before method="Startlog" pointcut-ref="AopMethod"/> <aop:after-returning method="Returnlog" pointcut-ref="AopMethod" returning="result"/> <aop:after-throwing method="Exceptionlog" pointcut-ref="AopMethod" throwing="exception"/> <aop:after method="Endlog~" pointcut-ref="AopMethod"/> </aop:aspect> </aop:config>
1.通知方法的执行顺序一般是:
try{ @Before 方法(); @AfterReturning }catch() { @AfterThrowing }finally { @After }
正常返回:@Before->@After->@AfterReturning
异常返回:@Before->@After->@AfterThrowing
@Before { try{ 环绕前置~~~~ 方法执行 环绕返回 } catch() { 环绕异常 }finally{ 环绕后置 } } @After @AfterReturning
正常情况:环绕前置通知->-前置通知>方法执行->环绕返回通知->环绕后置通知->后置通知->后置返回通知
异常情况:环绕前置通知->前置通知->环绕通知异常->环绕后置通知->后置通知->后置通知正常返回结果 (此处后置通知能正常返回,因为环绕通知已经把异常处理,后置通知无法发现错误)
3.多个切面一起执行时,先进来的切面后出去。先进后出原则!例如有A,B两个切面。
正常情况:A前置通知->B前置通知->方法执行->B后置通知->B后置返回通知->A后置通知->A后置返回通知
异常情况:同上