1. 程式人生 > >Spring AOP前置通知例項說明AOP相關概念

Spring AOP前置通知例項說明AOP相關概念

今天又看了下韓順平的SpringAOP的講解,講解的很透徹。仿照視訊自己使用下前置通知。

一、引出問題

  有個介面TestServiceInter,有兩個實現方法TestService和Test2Service。他們都有sayHello();我們的需求是在呼叫這兩個方法之前,要先完成寫日誌的功能;

二、菜鳥的想法

  我在各個實現類的sayHello()方法裡面寫上寫日誌的功能就是了。

  這樣實現存在的問題:程式碼冗餘。當所有實現類都要加上日誌功能的時候,需要寫很多重複程式碼

三、利用AOP前置通知實現此功能

3.1 第一步:我們需要定義一個介面  

package com.jdc.aop;

/** * @author DEllComputer * @Title: TestService * @ProjectName SpringAop * @Description: * @date 2018/12/251:38 PM */ public interface TestService { /**   * @Description:   * @param ${tags}   * @return ${return_type}   * @throws   * @author jdc   * @date 2018/12/25 1:39 PM   
*/ void sayHi(String name); }

3.2 第二步:實現介面

public class TestServiceImpl implements TestService {

    private String name;

    /**
      * @Description: say hi
      * @param ${tags}
      * @return ${return_type}
      * @throws
      * @author jdc
      * @date 2018/12/25 1:40 PM
      */
    @Override
    
public void sayHi(String name ) { System.out.println("hi:" + name); } public String getName() { return name; } public void setName(String name) { this.name = name; } }

3.3 第三步:實現前置通知(AOP中通知的概念就是實現增強程式碼邏輯的,比如這裡的記錄日誌)

/**
 * @author DEllComputer
 * @Title: MyBeforeAdvice
 * @ProjectName SpringAop
 * @Description: 寫日誌前置通知
 * @date 2018/12/251:42 PM
 */
public class MyBeforeAdvice implements MethodBeforeAdvice {
   
    /**
      * @Description: 寫日誌的功能
      * @param ${tags} 
      * @return ${return_type} 
      * @throws
      * @author jdc
      * @date 2018/12/25 1:44 PM 
      */
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("我是寫日誌的功能。");
    }
}

前置通知需要實現MethodBeforeAdvice介面,前置通知是在目標方法呼叫之前呼叫;

3.4 第四步:在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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 配置前置通知 -->
    <bean id="myBeforeAdvice" class="com.jdc.aop.advice.MyBeforeAdvice"/>

    <!-- 配置被代理物件 -->
    <bean id="logTestServiceImpl" class="com.jdc.aop.TestServiceImpl">
        <property name="name" value="Test"></property>
    </bean>

    <!-- 配置代理物件 -->
    <bean id="proxyFactoryBean"   class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 代理介面集 配置哪些介面要被代理 -->
        <property name="proxyInterfaces">
            <list>
                <value>com.jdc.aop.TestService</value>
            </list>
        </property>

        <!-- 把通知織入代理物件 -->
        <property name="interceptorNames">
            <value>myBeforeAdvice</value>
        </property>

        <!-- 配置被代理的物件 -->
        <property name="target" ref="logTestServiceImpl"/>


    </bean>


</beans>
ProxyFactoryBean是一個代理物件,如果我們被代理的物件實現了介面,Spring使用的是jdk動態代理技術實現的動態代理;所以我們要告訴代理物件,我們的哪些介面需要被代理,然後哪個物件需要被代理,我的增強實現應該怎麼被織入到代理物件(前置,後置,環繞....)

3.5 第五步:寫測試程式碼測試

public class TestMain {

    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        //獲取代理物件
        TestService log = (TestService) ac.getBean("proxyFactoryBean");
        log.sayHi("哈哈");

    }
}

注意這裡,我們需要獲取代理物件,而不是目標物件,不然不能呼叫前置通知的程式碼。