Spring 9:aop:config标签

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();
    }
}
--------------------- 
版权声明:本文为CSDN博主「萌中芢」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:

转载于:https://my.oschina.net/milletes/blog/3089285

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值