Spring 9:aop:config标签

xiaoxiao2025-10-02  3

aop:config标签

   使用aop的专用标签来完成相关的配置.(AOP标签库)    其中主要表现是使用AspectJ的expression的操作:   

execution(modifiers-pattern ret-type-pattern declaring-type-pattern name-pattern(param-pattern)

     throws-pattern)除了返回类型模式,名字模式和参数模式以外,     所有的部分都是可选的。 返回类型模式决定了方法的返回类型必须依次     匹配一个连接点。 你会使用的最频繁的返回类型模式是 *,它代表了匹     配任意的返回类型。 一个全称限定的类型名将只会匹配返回给定类型的方     法。名字模式匹配的是方法名。 你可以使用 * 通配符作为所有或者部分     命名模式。 参数模式稍微有点复杂:() 匹配了一个不接受任何参数的方     法, 而 (..) 匹配了一个接受任意数量参数的方法(零或者更多)。     模式 (*) 匹配了一个接受一个任何类型的参数的方法。 模式     (*,String) 匹配了一个接受两个参数的方法,第一个可以是任     意类型,第二个则必须是String类型        注意在使用之前需要在xml文件的beans标签中加入新的schame文件:并在Eclipse中进行关联配置   

<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" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

         下面给出一些常见切入点表达式的例子。  

      1)任意包下的任意类中的公共方法的执行:         

execution(public * *(..))

    2)任何一个以“set”开始的方法的执行:        

execution(* set*(..))

    3)AccountService 接口的任意方法的执行:           

execution(* com.briup.service.AccountService.*(..))

    4)定义在service包里的任意方法的执行:    

execution(* com.briup.service.*.*(..))

                     5)定义在service包或者子包里的任意方法的执行:       

execution(* com.briup.service..*.*(..)) execution(* com.briup.service..*.*(..)) or execution(* com.briup.dao..*.*(..))

    注意:         1.从spring容器中拿代理对象的时候也是要用目标对象的名字来拿。         2.没有实现任何接口的目标对象也能产生代理对象。       

<!-- 配置aop的代理 --> <aop:config> <!-- 定义一个切入点 并给切入点起名为myPointCut --> <!-- 切入点是一组连接点的集合 --> <aop:pointcut expression="execution(public * com.briup.aop.service.*.*(..))" id="myPointCut"/> <!-- 定义哪一个advice在哪一个切入点上面起作用 --> <aop:advisor advice-ref="beforeAdvice" pointcut-ref="myPointCut" /> </aop:config> <!-- expression="execution(public * com.briup.aop.service.*.*(..))" 这个引号""里面就是用表达式的方式来定义切入点,只要是符合我们这个表达式要求的 方法就是我们的连接点,连接点的集合就是我们要定义的切入点。 表达式中从左到右的*号: 第一个* 表示方法的返回类型不限。 第二个* 表示包中的任意一个类 第三个* 表示类中的任意一个方法 同时方法的参数也没有限制. -->

     注意:<aop:config proxy-target-class="true"> 如果这样配置则是强制使用CGLIB方式进行代理

例: 1.配置文件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.xsd "> <!-- 配置目标对象 --> <bean name="target" class="com.briup.pojo.BookServiceImpl"></bean> <bean name="target1" class="com.briup.pojo.ProductService"></bean> <!-- 配置通知 --> <bean name="around" class="com.briup.aop.spring.around.AroundAdviceTest"></bean> <!-- proxy-target-class构建代理对象的方式 true cglib代理 false jdk代理 目标对象直接配置bean, 获取代理对象基于bean标签的名字 --> <aop:config proxy-target-class="true"> <!-- 配置切面(目标对象哪些方法生效) expression表达式 id 选中方法构建切面的名字 com.briup.pojo.BookServiceImpl.saveBook(long, String) com.briup.pojo.ProductService.saveProduct(long, String) com.briup.pojo.*.save*(..) 注意:用该中方式配置切面 在构建目标对象方法的时候要注意方法名字 的书写 saveXXX --> <!-- <aop:pointcut expression="execution(* com.briup.pojo.*.save*(..))" id="mypointcut"/> --> <!-- 配置通知 切面 通知和切面绑定 pointcut直接写表达式 pointcut-ref指向表达式对象 pointcut|pointcut-ref一般情况只写一个 --> <!-- <aop:advisor advice-ref="around" pointcut-ref="mypointcut"/> --> <aop:advisor advice-ref="around" pointcut="execution(* com.briup.pojo.*.save*(..))"/> </aop:config> </beans> 2.测试类: package com.briup.aop.spring.aopConfig; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.briup.pojo.BookService; import com.briup.pojo.ProductService; public class aopConfigTest { public static void main(String[] args) { ClassPathXmlApplicationContext cp= new ClassPathXmlApplicationContext( "com/briup/aop/spring/aopConfig/aopConfig.xml"); BookService bs= cp.getBean("target",BookService.class); bs.saveBook(1, "lisi"); bs.list(); ProductService ps= cp.getBean("target1",ProductService.class); ps.saveProduct(1, "lisi"); ps.getProduct(); } }

※ 自定义通知类(自定义方法)

需要:aspectjweaver.jar包

在一个切面类中定个多个方法,根据xml文件的配置每个方法都可以织入到切入点的 不同位置,并且advice是在aop的标签中进行配置,不需要再写对应的advice类了     例如:   

//这个类相当于我们之前的切面类 //只不过这个切面类中有很多方法都可以织入到切入点上面 //我们可以控制把这里的任何一个方法织入到任何一个切入点上面 public class XmlHandler { public void beforeTest(JoinPoint p){ System.out.println(p.getSignature().getName()+" before..."); } public void afterTest(JoinPoint p){ System.out.println(p.getSignature().getName()+" after..."); } public void afterReturningTest(JoinPoint p){ System.out.println(p.getSignature().getName()+" afterReturning"); } //在和aroundAdvice结合的时候,这个方法一定要加上这个ProceedingJoinPoint类型的参数 public Object aroundTest(ProceedingJoinPoint pjp)throws Throwable{ //JoinPoint对象不能调用连接点所表示的方法 //ProceedingJoinPoint能调用连接点所表示的方法 pjp.proceed() System.out.println(pjp.getSignature().getName()+" is start.."); //调用到连接点方法 Object obj = pjp.proceed(); System.out.println(pjp.getSignature().getName()+" is end.."); return obj; } public void throwingTest(JoinPoint p,Exception ex){ System.out.println(p.getSignature().getName()+" is throwing..."+ex.getMessage()); } } xml文件配置: <!-- 配置dao层对象 --> <bean id="dao" class="com.briup.aop.dao.AccountDaoImpl"/> <!-- 配置目标对象 --> <bean name="target" class="com.briup.aop.service.AccountServiceImpl"> <property name="accountDao" ref="dao"></property> </bean> <!-- 配置切面类 --> <bean name="handler" class="com.briup.aop.xml.XmlHandler"></bean> <!-- 配置aop的代理 --> <aop:config> <!-- 定义切入点名为myPointCut --> <aop:pointcut expression="execution(public * com.briup.aop.service.*.*(..))" id="myPointCut"/> <!-- 定义切面类 以及需要使用的advice --> <aop:aspect id="aspect" ref="handler"> <!-- 表示beforeAdvice会把切面类handler中的beforeTest方法织入到名字叫myPointCut的切入点上面 --> <aop:before method="beforeTest" pointcut-ref="myPointCut"/> <!-- after表示不管方法是否正常结束都会起作用 --> <aop:after method="afterTest" pointcut-ref="myPointCut"/> <!-- after-returning表示方法正常结束才会起作用(抛异常时候不起作用) --> <aop:after-returning method="afterReturningTest" pointcut-ref="myPointCut"/> <aop:around method="aroundTest" pointcut-ref="myPointCut"/> <!-- throwing="ex"表示throwingTest方法中接收异常对象的名字一定要是ex --> <aop:after-throwing method="throwingTest" pointcut-ref="myPointCut" throwing="ex"/> </aop:aspect> </aop:config>

         注意:<aop:config proxy-target-class="true"> 如果这样配置则是强制使用CGLIB方式进行代理

例: 1.自定义通知类 package com.briup.aop.spring.defineAopConfig; import java.util.Arrays; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; /* * 自定义通知类(自定义的方法) */ public class DefineNoticeAdvice { /* * 前置通知, * 参数必须是joinpoint * */ public void beforeTest(JoinPoint point){ System.out.println("before......"); } /* * 后置通知 */ public void after(JoinPoint point){ //获取方法的镜像 // System.out.println(point.getSignature()); // //获取方法镜像的名字 // System.out.println( // point.getSignature().getName()); //获取目标对象方法执行的参数 // System.out.println( // Arrays.toString(point.getArgs())); //获取目标对象 // System.out.println(point.getTarget()); // System.out.println(point.getThis()); System.out.println("after...."); } public void afterReturn(JoinPoint point){ System.out.println("after1....."); } public Object around(ProceedingJoinPoint point){ // System.out.println(point.getTarget()); // System.out.println(point.getThis()); // System.out.println(point.getSignature()); // System.out.println(point.getArgs()); Object obj=null; try { System.out.println("before....."); //执行目标对象中的方法 obj=point.proceed(); System.out.println("after...."); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } return obj; } /* * 异常通知的方法 * 第一个参数joinPoint * 第二个参数异常类 */ public void throwE(JoinPoint point,Exception ex){ System.out.println( "exception..."+ex.getMessage()); } } 2.配置文件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.xsd "> <!-- 配置目标对象 --> <bean name="target" class="com.briup.pojo.BookServiceImpl"></bean> <bean name="target1" class="com.briup.pojo.ProductService"></bean> <!-- 自定义通知类的绑定 --> <bean name="notice" class="com.briup.aop.spring.defineAopConfig.DefineNoticeAdvice"></bean> <aop:config> <!-- 指定切面 --> <aop:pointcut expression="execution(* com.briup.pojo.*.save*(..))" id="mypointcut"/> <!-- 指定方法和切面绑定 此时需要添加jar包aspectjweaver.jar(如何把通知作用在切面上,切面的植入) ref指向自定义通知的类--> <aop:aspect ref="notice"> <!--method指向自定义类中的方法 pointcut写表达式,作用与哪些方法 pointcut-ref 指向切面对象 --> <!-- 前置通知 --> <!-- <aop:before method="beforeTest" pointcut-ref="mypointcut"/> --> <!-- 后置通知 ,目标对象执行方法 出异常的时候一定执行的通知 --> <!-- <aop:after method="after" pointcut-ref="mypointcut"/> --> <!-- 后置通知,目标对象执行方法 出异常的时候不执行的通知 --> <!-- <aop:after-returning method="afterReturn" pointcut-ref="mypointcut"/> --> <!-- 环绕通知 --> <!-- <aop:around method="around" pointcut-ref="mypointcut"/> --> <!-- 异常通知 throwing异常的名字 注意:该名字和自定义通知中方法的 参数保持一致 --> <aop:after-throwing method="throwE" pointcut-ref="mypointcut" throwing="ex"/> </aop:aspect> </aop:config> </beans> 3. 测试类: package com.briup.aop.spring.defineAopConfig; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.briup.pojo.BookService; import com.briup.pojo.ProductService; public class defineNoticeaopConfigTest { public static void main(String[] args) { ClassPathXmlApplicationContext cp= new ClassPathXmlApplicationContext( "com/briup/aop/spring/defineAopConfig/defineaopconfig.xml"); BookService bs= cp.getBean("target",BookService.class); bs.saveBook(1, "lisi"); bs.list(); // ProductService ps= // cp.getBean("target1",ProductService.class); // ps.saveProduct(1, "lisi"); // ps.getProduct(); } }

※ 使用注解配置AOP:其实就是在上面的类XmlHandler中加入上注解,然后去掉xml中的aop标签配置,这里把类改名为AnnotationHandler,    

例子: @Component @Aspect public class AnnotationHandler { /* * 在一个方法上面加上注解来定义切入点 * 这个切入点的名字就是这个方法的名字 * 这个方法本身不需要有什么作用 * 这个方法的意义就是:给这个 @Pointcut注解一个可以书写的地方 * 因为注解只能写在方法、属性、类的上面,并且方法名作为切入点的名字 * */ @Pointcut("execution(public * com.briup.aop.service..*.*(..))") public void myPointCut(){} //注:这里面的所有方法的JoinPoint类型参数都可以去掉不写,如果确实用不上的话 @Before("myPointCut()") public void beforeTest(JoinPoint p){ System.out.println(p.getSignature().getName()+" before..."); } /* * @After和@AfterReturning * * @After标注的方法会在切入点上的方法结束后被调用(不管是不是正常的结束). * @AfterReturning标注的方法只会在切入点上的方法正常结束后才被调用. * */ @After("myPointCut()") public void afterTest(JoinPoint p){ System.out.println(p.getSignature().getName()+" after..."); } @AfterReturning("myPointCut()") public void afterReturningTest(JoinPoint p){ System.out.println(p.getSignature().getName()+" afterReturning"); } @Around("myPointCut()") public Object aroundTest(ProceedingJoinPoint pjp)throws Throwable{ System.out.println(pjp.getSignature().getName()+" is start.."); //调用连接点的方法去执行 Object obj = pjp.proceed(); System.out.println(pjp.getSignature().getName()+" is end.."); return obj; } //在切入点中的方法执行期间抛出异常的时候,会调用这个 @AfterThrowing注解所标注的方法 @AfterThrowing(value="myPointCut()",throwing="ex") public void throwingTest(JoinPoint p,Exception ex){ System.out.println(p.getSignature().getName()+" is throwing..."+ex.getMessage()); } } xml配置:注意给例子中使用的其他的类上面也使用注解 <aop:aspectj-autoproxy/> <context:component-scan base-package="com.briup.aop"/>

    注意:<aop:aspectj-autoproxy proxy-target-class="true"/>这样配置则是强制使用CGLIB进行代理

例: 1. package com.briup.pojo; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service; @Component("target") //@Controller //@Service //@Repository public class BookServiceImpl implements BookService{ @Override public void saveBook(long id, String name) { // TODO Auto-generated method stub System.out.println("saveBook...."); //int i=10/0; } @Override public String get(long id) { // TODO Auto-generated method stub System.out.println("get...."); return "test...ok"; } @Override public void list() { // TODO Auto-generated method stub System.out.println("list...."); } @Override public void setTest() { // TODO Auto-generated method stub System.out.println("set....."); } @Override public int getAge() { // TODO Auto-generated method stub System.out.println("getAge()...."); return 23; } } package com.briup.pojo; import org.springframework.stereotype.Component; @Component("target1") public class ProductService { public void saveProduct(long id,String name){ System.out.println("saveProduct..."); } public int getProduct(){ System.out.println("getProduct...."); return 33; } } 2.自定义通知类 package com.briup.aop.spring.AnnoAopConfig; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /* * 自定义通知类(自定义的方法) * @Aspect表示单前类中的方法全是 * 作用切面上的通知 * 1.注解的方式构建切面(方法) * 2.通知上面加入注解 */ @Component @Aspect public class AnnoNoticeAdvice { /* * 构建切面的方法,切面的名字 * 就是methodName(), * 该方法不使用 */ //@Pointcut(value="") @Pointcut("execution(* com.briup.pojo.*.save*(..))") public void mypointcut(){} /* * 前置通知, * 参数必须是joinpoint * @Before注解该方法前置通知 * 参数是切面的名字 */ @Before("mypointcut()") public void beforeTest(JoinPoint point){ System.out.println("before......"); } /* * 后置通知 */ @After("mypointcut()") public void after(JoinPoint point){ //获取方法的镜像 // System.out.println(point.getSignature()); // //获取方法镜像的名字 // System.out.println( // point.getSignature().getName()); //获取目标对象方法执行的参数 // System.out.println( // Arrays.toString(point.getArgs())); //获取目标对象 // System.out.println(point.getTarget()); // System.out.println(point.getThis()); System.out.println("after...."); } @AfterReturning("mypointcut()") public void afterReturn(JoinPoint point){ System.out.println("after1....."); } @Around("mypointcut()") public Object around(ProceedingJoinPoint point){ // System.out.println(point.getTarget()); // System.out.println(point.getThis()); // System.out.println(point.getSignature()); // System.out.println(point.getArgs()); Object obj=null; try { System.out.println("before....."); //执行目标对象中的方法 obj=point.proceed(); System.out.println("after...."); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } return obj; } /* * 异常通知的方法 * 第一个参数joinPoint * 第二个参数异常类 * @AfterThrowing中throwing对应的名字和参数 * 异常的名字一致 */ @AfterThrowing(value="mypointcut()", throwing="ex") public void throwE(JoinPoint point,Exception ex){ System.out.println( "exception..."+ex.getMessage()); } } 3.配置文件 <?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" xmlns:context="http://www.springframework.org/schema/context" 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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> <!-- 配置目标对象 --> <!-- <bean name="target" class="com.briup.pojo.BookServiceImpl"></bean> <bean name="target1" class="com.briup.pojo.ProductService"></bean> --> <!-- 自动给当前的目标对象绑定通知 获取代理对象基于目标对象bean标签的名字 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <context:component-scan base-package="com.briup.aop.spring.AnnoAopConfig,com.briup.pojo"></context:component-scan> </beans> 4.测试类: package com.briup.aop.spring.AnnoAopConfig; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.briup.pojo.BookService; import com.briup.pojo.ProductService; public class AnnoaopConfigTest { public static void main(String[] args) { ClassPathXmlApplicationContext cp= new ClassPathXmlApplicationContext( "com/briup/aop/spring/AnnoAopConfig/annoaopconfig.xml"); BookService bs= cp.getBean("target",BookService.class); bs.saveBook(1, "lisi"); bs.list(); // ProductService ps= // cp.getBean("target1",ProductService.class); // ps.saveProduct(1, "lisi"); // ps.getProduct(); } }

 

转载请注明原文地址: https://www.6miu.com/read-5037239.html

最新回复(0)