亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring學習筆記AOP(一)

發布時間:2020-07-11 15:08:01 來源:網絡 閱讀:367 作者:luchunli1985 欄目:開發技術

魯春利的工作筆記,好記性不如爛筆頭



面向方面的編程(AOP) 是一種編程范式,旨在通過允許橫切關注點的分離,提高模塊化。

package com.invicme.apps.aop.proxy;

import org.apache.log4j.Logger;

/**
 * 
 * @author lucl
 * 
 * 數學計算實現類
 *
 */
public class ArithmeticCalculateImpl implements ArithmeticCalculate {
    
    private static final Logger logger = Logger.getLogger(ArithmeticCalculateImpl.class);
    
    private int i = 0;
    private int j = 0;
    
    public ArithmeticCalculateImpl () {
        this(0, 0);
    }
    
    public ArithmeticCalculateImpl (int i, int j) {
        this.i = i;
        this.j = j;
    }
    
    @Override
    public int add(int i, int j) {
        logger.info("The method add was invoke with args [" + i + ", " + j + "]");
        int sum = i + j;
        logger.info("The method add ends with result [" + sum + "]");
        return sum;
    }

    @Override
    public int div(int i, int j) throws DivisorIsZeroException {
        logger.info("The method div was invoke with args [" + i + ", " + j + "]");
        if (j == 0) {
            throw new DivisorIsZeroException("除數不可為0");
        }
        int result = i / j;
        logger.info("The method div ends with result [" + result + "]");
        return result;
    }

    @Override
    public String validateNum(String level, int i) {
        logger.info("The method validateNum was invoke with args [" + level + ", " + i + "]");
        String result = this.getMsg(i);
        logger.info("The method validateNum ends with result [" + result + "]");
        return result;
    }

    private String getMsg (int i) {
        if (i > 0) {
            return "正數";
        }
        return "負數";
    }
}

對于類ArithmeticCalculateImpl的日志通過在方法中加入logger.info來記錄的,存在大量的冗余代碼,特別是如果在項目開發階段未通過這種方式記錄日志,那么希望記錄日志時需要修改代碼加入日志邏輯(OOP開發模式)。


AOP為開發者提供一種進行橫切關注點分離并織入的機制,把橫切關注點分離,然后通過某種技術織入到系統中,從而無耦合的完成了我們的功能。


Aspect(切面):指橫切性關注點的抽象即為切面,它與類相似,只是兩者的關注點不一樣,類是對物體特征的抽象,而切面橫切性關注點的抽象.
Joinpoint(連接點):所謂連接點是指那些被攔截到的點。在Spring中,這些點指的是方法,因為spring只支持方法類型的連接點,實際上Joinpoint還可以是Field或類構造器。
Pointcut(切入點):所謂切入點是指我們要對哪些Joinpoint進行攔截的定義。
Advice(通知):所謂通知是指攔截到Joinpoint之后所要做的事情。通知分為前置通知,后置通知,異常通知,最終通知,環繞通知。
Target(目標對象):代理的目標對象。
Weave(織入):指將aspects應用到target對象并導致proxy對象創建的過程稱為織入。
Introduction(引入):在不修改類代碼的前提下, Introduction可以在運行期為類動態地添加一些方法或Field。


Spring提供了4種實現AOP的方式:

  • 經典的基于代理的AOP

  • @AspectJ注解驅動的切面

  • 純POJO切面

  • 注入式AspectJ切面


前三種都是Spring基于代理的AOP變體,因此Spring對AOP的支持局限于方法攔截。如果AOP需求超過了簡單方法的攔截范疇(如構造器或屬性攔截),那么應該考慮在AspectJ里實現切面,利用Spring的DI把Spring Bean注入到AspectJ切面中。


經典的基于代理的AOP:

Spring支持五種類型的通知:
Before(前)            org.apringframework.aop.MethodBeforeAdvice
After-returning(返回后) org.springframework.aop.AfterReturningAdvice
After-throwing(拋出后)  org.springframework.aop.ThrowsAdvice
Arround(周圍)          org.aopaliance.intercept.MethodInterceptor
Introduction(引入)     org.springframework.aop.IntroductionInterceptor


實現步驟:

1.創建通知:實現這幾個接口,把其中的方法實現了
2.定義切點和通知者:在Spring配制文件中配置這些信息
3.使用ProxyFactoryBean來生成代理。


業務代碼(接口):

package com.invicme.apps.aop.proxy;

/**
 * 
 * @author lucl
 * 
 * 數學計算接口類
 *
 */
public interface ArithmeticCalculate {
    public int add (int i, int j);
    public int div (int i, int j) throws DivisorIsZeroException;
    public String validateNum (String level, int i);
}

業務代碼(實現類):

package com.invicme.apps.aop.proxy;

import org.apache.log4j.Logger;

/**
 * 
 * @author lucl
 * 
 * 數學計算實現類
 *
 */
public class ArithmeticCalculateImpl implements ArithmeticCalculate {
    
    private static final Logger logger = Logger.getLogger(ArithmeticCalculateImpl.class);
    
    private int i = 0;
    private int j = 0;
    
    public ArithmeticCalculateImpl () {
        this(0, 0);
    }
    
    public ArithmeticCalculateImpl (int i, int j) {
        this.i = i;
        this.j = j;
    }
    
    @Override
    public int add(int i, int j) {
        logger.info("The method add was invoke with args [" + i + ", " + j + "]");
        int sum = i + j;
        logger.info("The method add ends with result [" + sum + "]");
        return sum;
    }

    @Override
    public int div(int i, int j) throws DivisorIsZeroException {
        logger.info("The method div was invoke with args [" + i + ", " + j + "]");
        if (j == 0) {
            throw new DivisorIsZeroException("除數不可為0");
        }
        int result = i / j;
        logger.info("The method div ends with result [" + result + "]");
        return result;
    }

    @Override
    public String validateNum(String level, int i) {
        logger.info("The method validateNum was invoke with args [" + level + ", " + i + "]");
        String result = this.getMsg(i);
        logger.info("The method validateNum ends with result [" + result + "]");
        return result;
    }

    private String getMsg (int i) {
        if (i > 0) {
            return "正數";
        }
        return "負數";
    }
}

希望切入的日志操作:

package com.invicme.apps.aop.proxy;

import java.lang.reflect.Method;
import java.util.Arrays;

import org.apache.log4j.Logger;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

/**
 * 
 * @author lucl
 * 
 */
public class LogAdapter implements MethodBeforeAdvice, AfterReturningAdvice {
    private static final Logger logger = Logger.getLogger(LogAdapter.class);

    /**
     * 目標對象的方法執行之前打印日志
     */
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        logger.info(target.getClass().getName() + "@" + method.getName() + " with args " + Arrays.asList(args) + " invoke.");
    }
    
    /**
     * 目標對象的方法執行之后打印日志
     */
    @Override
    public void afterReturning(Object returnValue, Method method,
            Object[] args, Object target) throws Throwable {
        logger.info(target.getClass().getName() + "@" + method.getName() + " ends with result " + returnValue + " .");
    }
    
}

Spring配置文件:

<?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: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/context http://www.springframework.org/schema/context/spring-context.xsd">
    
    <!-- 業務類 -->
    <bean id="calculate" class="com.invicme.apps.aop.proxy.ArithmeticCalculateImpl" />
    
    <!-- 切入的日志類 -->
    <bean id="logAdapter" class="com.invicme.apps.aop.proxy.LogAdapter" />
    
    <!-- 定義正則表達式切點 -->
    <bean id="loggerPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
        <!-- 單個方法 -->
        <!-- 
          <property name="pattern" value=".*add"/>
           -->
          <property name="patterns">
              <list>
                  <value>.*add</value>
                  <value>.*iv</value>
                  <value>.validate*</value>
              </list>
          </property> 
    </bean>
    
    <bean id="loggerAdapterAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
         <property name="advice" ref="logAdapter"/>
         <property name="pointcut" ref="loggerPointcut"/>
    </bean>
    
    <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
         <property name="target" ref="calculate"/>
         <property name="interceptorNames" value="loggerAdapterAdvisor" />
         <property name="proxyInterfaces" value="com.invicme.apps.aop.proxy.ArithmeticCalculate" />
    </bean>
</beans>

Junit單元測試類:

package com.test.apps.spring.aop;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.invicme.apps.aop.proxy.ArithmeticCalculate;
import com.invicme.apps.aop.proxy.DivisorIsZeroException;

/**
 * 
 * @author lucl
 *
 */
public class TestSpringProxyFactoryBean {
    @Test
    public void testProxyFactoryBean() {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-context-aop.xml");
        ArithmeticCalculate calculate = context.getBean("proxyFactoryBean", ArithmeticCalculate.class);
        calculate.add(1, 2);
        System.out.println("----------------------------------------------------------------");
        try {
            calculate.div(12, 3);
        } catch (DivisorIsZeroException e) {
            e.printStackTrace();
        }
    }
}

輸出結果:

Spring學習筆記AOP(一)

說明:

    ProxyFactoryBean是一個代理,我們可以把它轉換為proxyInterfaces中指定的實現該interface的代理對象。   

    通過代理模式可以獲取到業務日志中希望輸出的日志內容。


    OK!這是我們想要的結果,但是上面這個過程貌似有點復雜,尤其是配置切點跟通知,Spring提供了一種自動代理的功能,能讓切點跟通知自動進行匹配,修改配置文件如下:

<?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: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/context http://www.springframework.org/schema/context/spring-context.xsd">
    
    <!-- 業務類 -->
    <bean id="calculate" class="com.invicme.apps.aop.proxy.ArithmeticCalculateImpl" />
    
    <!-- 切入的日志類 -->
    <bean id="logAdapter" class="com.invicme.apps.aop.proxy.LogAdapter" />
    
    <!-- 定義正則表達式切點 -->
    <bean id="loggerPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
        <!-- 單個方法 -->
        <!-- 
          <property name="pattern" value=".*add"/>
           -->
          <property name="patterns">
              <list>
                  <value>.*add</value>
                  <value>.*iv</value>
                  <value>.validate*</value>
              </list>
          </property> 
    </bean>
    
    <bean id="loggerAdapterAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
         <property name="advice" ref="logAdapter"/>
         <property name="pointcut" ref="loggerPointcut"/>
    </bean>
    
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
    
    <!-- <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
         <property name="target" ref="calculate"/>
         <property name="interceptorNames" value="loggerAdapterAdvisor" />
         <property name="proxyInterfaces" value="com.invicme.apps.aop.proxy.ArithmeticCalculate" />
    </bean> -->
</beans>


執行程序:

package com.test.apps.spring.aop;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.invicme.apps.aop.proxy.ArithmeticCalculate;
import com.invicme.apps.aop.proxy.DivisorIsZeroException;

/**
 * 
 * @author lucl
 *
 */
public class TestSpringProxyFactoryBean {
    @Test
    public void testProxyFactoryBean() {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-context-aop.xml");
        /*ArithmeticCalculate calculate = context.getBean("proxyFactoryBean", ArithmeticCalculate.class);*/
        ArithmeticCalculate calculate = context.getBean("calculate", ArithmeticCalculate.class);
        calculate.add(1, 2);
        System.out.println("----------------------------------------------------------------");
        try {
            calculate.div(12, 3);
        } catch (DivisorIsZeroException e) {
            e.printStackTrace();
        }
    }
}


說明:org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator能夠為方法匹配的bean自動創建代理!


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

蒙自县| 大化| 乳源| 磐安县| 南皮县| 太白县| 谷城县| 上犹县| 陕西省| 丹阳市| 贵州省| 长治市| 夏邑县| 拜城县| 含山县| 商水县| 罗山县| 定安县| 万宁市| 拉孜县| 柳江县| 淮阳县| 唐河县| 景德镇市| 千阳县| 洛隆县| 马关县| 泸水县| 蒙山县| 东海县| 鹤庆县| 临邑县| 四子王旗| 明星| 宜城市| 股票| 仙桃市| 大厂| 南丰县| 中宁县| 兴化市|