1. 程式人生 > >Spring框架:AOP程式設計

Spring框架:AOP程式設計

實現方法:動態代理設計模式

  • JDK 的動態代理:針對實現了介面的類產生代理。InvocationHandler介面
  • CGlib 的動態代理:針對沒有實現介面的類產生代理,應用的是底層的位元組碼增強的技術 生成當前類的子類物件,MethodInterceptor介面

JDK動態代理

  1. 建立介面和實現類

  2. 建立代理類,實現InvocationHandler介面

     //建立被代理物件
        private UserDao dao;
        public  Agency(UserDao dao){
            this.dao=dao;
        }
        //建立代理物件
        public
    UserDao CreatAgency(){ // Proxy.newProxyInstance(類的載入器,物件實現的介面,呼叫者) UserDao userdao = (UserDao)Proxy.newProxyInstance(dao.getClass().getClassLoader(), dao.getClass().getInterfaces(), this); return userdao; } public Object invoke(Object proxy, Method method, Object[
    ] args) throws Throwable { System.out.println("一切之初"); Object om = method.invoke(dao, args); System.out.println("終焉"); return om; } ```
  3. 測試

  		//獲取代理物件
       *//* UserDao u = new U();*//*
        //建立代理類物件
        Agency agency = new Agency(u);
        //建立代理物件
        UserDao um =
agency.CreatAgency(); //呼叫方法 um.sing();
CGlib動態代理

實現介面MethodInterceptor,來自import org.springframework.cglib.proxy.MethodInterceptor;不要錯誤了

  1. 建立普通類:方法

  2. 建立代理器,實現MethodInterceptor介面

    程式碼與上一個相同,區別的地方時建立代理物件的方法

     //建立代理物件的方法
        public UsersDaoImpl createdaili(){
            Enhancer en=new Enhancer();//建立核心類
            en.setSuperclass(user.getClass());//為其設定父類
            en.setCallback(this);//設定回撥
            return (UsersDaoImpl)en.create();
        }
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            執行方法之前語句塊
            Object o1 = methodProxy.invokeSuper(o, objects);
            執行方法之後語句塊
            return o1;
        }
    
  3. 測試:與JDK動態代理測試方法一致

AOP實現:以上兩種方式程式碼自動判斷實現

  1. 新增jar包
  2. 建立Aop增強類(本質普通類)
    1. 前置通知
    2. 返回通知
    3. 後置異常通知
    4. 後置最終通知
    5. 環繞通知:有返回值,必須返回,否則報錯
	public  Object around(ProceedingJoinPoint point) throws Throwable{}
  1. xml檔案新增名稱空間aop
	xmlns:aop="http://www.springframework.org/schema/aop"
   http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
  1. 設定配置檔案

       <!--建立目標類物件-->
        <bean name="userService" class="com.itqf.spring.service.UserServiceImpl" />
        <!--配置增強類物件-->
        <bean name="myAdvice" class="com.itqf.spring.aop.MyAdivce" />
        <!-- 配置將增強織入目標物件-->
        <aop:config>
            <aop:pointcut id="pc" expression="execution(* com.itqf.spring.service.*ServiceImpl.*(..))"/>
            <aop:aspect ref="myAdvice">
                     <aop:before method="before" pointcut-ref="pc" />
                     <aop:after-returning method="afterReturning" pointcut-ref="pc" />
                     <aop:around method="around" pointcut-ref="pc" />
                     <aop:after-throwing method="afterException" pointcut-ref="pc" />
                     <aop:after method="after" pointcut-ref="pc" />
            </aop:aspect>
        </aop:config>
    注意:(1)環繞增強需要使用ProceedingJoinPoint 作為引數(2)注意標籤順序
    
  2. 切入點匹配規則:

    public * addUser(com.pb.entity.User):“*”表示匹配所有型別的返回值。
      示例:public int addUser(User u);
           public String addUser(User u);
    public void *(com.pb.entity.User):“*”表示匹配所有方法名。
       示例:public void selectUser(User u);  
            public void a(User u);
    public void addUser (..):“..”表示匹配所有引數個數和型別。
       示例: public void addUser(int a)
             public void addUser(int b,int c)
    * com.pb.service.*.*(..):匹配com.pb.service 包下所有類的所有方法。
       示例:  public  void com.pb.service.A.a();
               public  String  com.pb.service.B.a();
    * com.pb.service..*(..):匹配com.pb.service 包及子包下所有類的所有方法
    
    獲取切入點資訊

    通過aop類,新增引數JoinPoint物件獲取資訊

    			"切入點物件:"+jp.getTarget().getClass().getSimpleName();
        		"切入點方法:"+jp.getSignature();
         		"切入點的引數:"+jp.getArgs()[0];
    

特殊增強——Advisor前置增強實現步驟

  1. 建立增強類,實現MethodBeforeAdvice介面
  2. 在配置檔案,aop配置切入點後,加入
 <aop:advisor advice-ref="增強類物件的id" pointcut-ref="切入點物件的id"/>

註解實現Aop

  1. 啟動aspectj註解

    		<aop:aspectj-autoproxy/> 
    
  2. 在切面類上新增@Aspect

  3. 定義切面方法(任意),新增切入點註解@Pointcut(“execution(切入路徑)”)

  4. @Before 前置 @After 最終 @Around 環繞 @AfterReturning 後置 @AfterThrowing 異常

eg:		@Before("切入方法()")