Spring入门6---AOP1

来源:互联网 发布:最难破解的网络验证 编辑:程序博客网 时间:2024/05/06 13:15

Spring的AOP实现

1.纯java实现,无需特殊的编译过程,不需要控制类加载层次

2.目前只支持方法执行连接点(通知Spring Bean的方法执行)

3.不是为了提供最完整的AOP实现(尽管它非常强大);而是侧重于提供一种AOP实现和Spring IoC容器之间的整合,用于帮助解决企业应用中的常见问题

4.Spring AOP不会与AspectJ竞争,从而提供综合全面的AOP解决方案

Spring所有的切面和通知器都必须放在一个<aop:config>内(可以配置包含多个<aop:config>元素),每一个<aop:config>可以包含pointcut , advisor 和 aspect元素

(它们必须按照这个顺序进行声明)


先来一个简单用例

1.  创建一个切面类

package aop.schema.advice;public class MyAspect {public void before(){System.out.println("MyAspect:before");}}


2.  创建一个需要进行AOP的业务类

package aop.schema.advice.biz;public class AspectBiz {public void biz(){System.out.println("AspectBiz:biz");}}


3.  在xml中配置切面

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:aop="http://www.springframework.org/schema/aop"    xsi:schemaLocation="http://www.springframework.org/schema/beans         http://www.springframework.org/schema/beans/spring-beans.xsd          http://www.springframework.org/schema/aop         http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"><bean id="myAspect" class="aop.schema.advice.MyAspect"></bean><bean id="aspectBiz" class="aop.schema.advice.biz.AspectBiz"></bean><aop:config><aop:aspect id="myAspectAOP" ref="myAspect">    <!--该表达式的意思是,切入点是  aop.schema.advice.biz.AspectBiz 类中的所有方法 --><aop:pointcut expression="execution(* aop.schema.advice.biz.AspectBiz.*(..))" id="myPiontcut"/><!--指定前置通知, method中的名称即是 myAspect中的方法名,pointcut-ref 指向某一个切入点   -->  <aop:before method="before" pointcut-ref="myPiontcut"/> </aop:aspect></aop:config> </beans>


4. 测试

package test.aop;import org.junit.Test;import org.junit.runner.RunWith;import org.junit.runners.BlockJUnit4ClassRunner;import org.springframework.context.support.ClassPathXmlApplicationContext;import annotation.BeanAnnotation;import aop.schema.advice.biz.AspectBiz;@RunWith(BlockJUnit4ClassRunner.class)public class TestAopSchemaAdvice {private ClassPathXmlApplicationContext context;@Testpublic void testBean(){ context = new ClassPathXmlApplicationContext("spring-aop-schema-advice.xml"); AspectBiz ab = (AspectBiz) context.getBean("aspectBiz"); ab.biz();}}


输出:

MyAspect:before

AspectBiz:biz


还可以指定 切入点方法执行完之后调用的通知 <aop:after-returning >

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:aop="http://www.springframework.org/schema/aop"    xsi:schemaLocation="http://www.springframework.org/schema/beans         http://www.springframework.org/schema/beans/spring-beans.xsd          http://www.springframework.org/schema/aop         http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"><bean id="myAspect" class="aop.schema.advice.MyAspect"></bean><bean id="aspectBiz" class="aop.schema.advice.biz.AspectBiz"></bean><aop:config><aop:aspect id="myAspectAOP" ref="myAspect">    <!--该表达式的意思是,切入点是  aop.schema.advice.biz.AspectBiz 类中的所有方法 --><aop:pointcut expression="execution(* aop.schema.advice.biz.AspectBiz.*(..))" id="myPiontcut"/><!--指定前置通知, method中的名称即是 myAspect中的方法名,pointcut-ref 指向某一个切入点   -->  <aop:before method="before" pointcut-ref="myPiontcut"/>  <!--指定在 切入点方法返回之后调用的通知  ,method中的名称即是 myAspect中的方法名  --><aop:after-returning method="afterReturning" pointcut-ref="myPiontcut"/> </aop:aspect></aop:config> </beans>

在切面类中加入 afterReturning方法

package aop.schema.advice;public class MyAspect {public void before(){System.out.println("MyAspect:before");}public void afterReturning(){System.out.println("MyAspect:afterReturning");}}

测试结果:

MyAspect:before

AspectBiz:biz

MyAspect:afterReturning


除了 after-returning 之外

1. 还可以指定抛出异常之后调用的通知 , 若抛出异常,则after-returning不会执行

<aop:after-throwing method="afterThrowing" pointcut-ref="myPiontcut"/>


2. 指定方法后置通知 after ,如果after定义在 after-returning之前,就会先被调用,反之,后被调用

当有异常抛出时 执行throwing ,但是由于是非正常结束,所以after-returning就是不会执行了,但是after 是不管你是否正常结束,都一定会执行。

<aop:after method="after" pointcut-ref="myPiontcut"/> 


2. 指定环绕通知 ,注意 通知方法的第一个参数必须是ProceedingJoinPoint类型

例如:

<!--环绕通知 ,  通知方法的第一个参数必须是 ProceedingJoinPoint类型 --><aop:around method="around" pointcut-ref="myPiontcut"/> 

在myAspect定义 around方法

public Object around(ProceedingJoinPoint pjp){Object obj =null;try {System.out.println("MyAspect: around 1");obj = pjp.proceed();System.out.println("MyAspect: around 2");} catch (Throwable e) {// TODO Auto-generated catch blocke.printStackTrace();}return obj;}

运行结果


MyAspect:before

MyAspect: around 1

AspectBiz:biz

MyAspect: around 2

MyAspect:after

MyAspect:afterReturning





0 0