Spring AOP(1)- 前置增強 實現

實現原理:

前置增強完成功能:在目標類的方法執行之前嵌入增強邏輯.
實現原理:
1. 實現接口 MethodBeforeAdvice,重寫函數 before ,在函數before中實現需要插入目標方法之前的邏輯代碼
2. 利用ProxyFactoryBean代理類調用目標類方法 或者使用AOP動態代理
3.配置Spring XML

定義接口類

package com.advice;

import com.smart.domain.User;

import java.sql.SQLException;

/**
 * @author Duoduo
 * @version 1.0
 * @date 2017/4/22 18:58
 */
public interface IUserDao {
    int addUser(User user);
    int updateUser(User user);
    void deleteUser(User user);
    void removeUser(User user) throws SQLException;
}

接口實現類

package com.advice;

import com.smart.domain.User;

import java.sql.SQLException;

/**
 * @author Duoduo
 * @version 1.0
 * @date 2017/4/22 19:00
 */
public class UserDaoImpl implements IUserDao {
    @Override
    public int addUser(User user) {
        System.out.println("Add user");
        return 0;
    }

    @Override
    public int updateUser(User user) {
        System.out.println("Update user");
        return 0;
    }

    @Override
    public void deleteUser(User user) {
        //throw new RuntimeException("exception test");
    }

    @Override
    public void removeUser(User user) throws SQLException {
        //throw new SQLException("SQLException Test");
    }
}

定義前置增強類

package com.advice;

import com.smart.domain.User;
import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

/**
 * 前置增強:在目標類的方法執行之前嵌入增強邏輯
 * @author Duoduo
 * @version 1.0
 * @date 2017/4/22 19:01
 */
public class AddUserBeforAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {

        User user = (User)args[0];
        //編寫前置增強邏輯 ... 
        System.out.println("Before Add user for user name :"+user.getUserName());
    }
}

Spring XML 配置 有兩種方式

1.配置代理工廠
特別注意:代理工廠是 ProxyFactoryBean 不是 ProxyFactory

<!-- 代理設置 -->
<bean id="userDaoImpl" class="com.advice.UserDaoImpl"/>
<bean id="addUserBeforAdvice" class="com.advice.AddUserBeforAdvice"/>
<bean id="addUserAfterAdvice" class="com.advice.AddUserAfterAdvice"/>

<bean id="addUserProxyFactory" class="org.springframework.aop.framework.ProxyFactoryBean"
      p:proxyInterfaces="com.advice.IUserDao"
      p:interceptorNames="addUserBeforAdvice"
      p:target-ref="userDaoImpl"/>

2.配置動態代理,使用AOP配置

注意:expression是一個表達式。
其中: .. 表示所有參數 *表示所有方法
例如:<aop:pointcut id="pointcut" expression="execution(* com.advice.UserDaoImpl.*(..))"/> 表示攔截UserDaoImpl所有的方法
<aop:pointcut id="pointcut" expression="execution(* com.advice.*.*(..))"/>表示攔截advice下的所有的類的所有方法
 <bean id="userDaoImpl" class="com.advice.UserDaoImpl"/>
 <bean id="addUserBeforAdvice" class="com.advice.AddUserBeforAdvice"/>
 <aop:config expose-proxy="true">
        <!--<aop:pointcut id="pointcut" expression="execution(* com.advice.UserDaoImpl.*(..))"/>-->
        <aop:pointcut id="pointcut" expression="execution(* com.advice.UserDaoImpl.addUser(..))"/>
        <aop:advisor advice-ref="addUserBeforAdvice" pointcut-ref="pointcut"/>
    </aop:config>

Junit測試 – 使用代理工廠模式

兩種調用方式:
1.根據XML配置來進行調用測試
2.自己創建代理來進行測試

另種方法都需要注意:此處代理獲取的是代理Bean,指向的是Interface的代理。

@Test
public  void addUserAdivceTest(){

    /*IUserDao userDao = new UserDaoImpl();
    BeforeAdvice beforeAdvice = new AddUserBeforAdvice();

    //創建代理工廠
    ProxyFactory proxyFactory = new ProxyFactory();
    //設置代理目標類
    proxyFactory.setTarget(userDao);

    //爲代理添加增強
    proxyFactory.addAdvice(beforeAdvice);
    //生成代理實例
    //代理爲指向Interface的代理
    IUserDao proxyUserDao = (IUserDao)proxyFactory.getProxy();
    proxyUserDao.addUser(user);*/

    System.out.println("************ addUserAdivceTest ************");
    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-another-context.xml");
    //代理爲指向Interface的代理
    IUserDao userDaoProxyFactory = (IUserDao) context.getBean("addUserProxyFactory");
    userDaoProxyFactory.addUser(user);


}

測試結果

** addUserAdivceTest **
四月 23, 2017 1:23:57 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@add0edd: startup date [Sun Apr 23 13:23:57 CST 2017]; root of context hierarchy
四月 23, 2017 1:23:57 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [spring-another-context.xml]
Before Add user for user name :Test User Name
Add user

Junit測試 – 使用AOP動態代理模式

 @Test
    public void testBefore() throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "classpath:spring-advice.xml");
        IUserDao userDao = (IUserDao) context.getBean("userDaoImpl");
        userDao.addUser(new User("username", "password", true, "ADMIN"));
        userDao.updateUser(new User("username", "password", true, "ADMIN"));
    }

測試結果

AddUserBeforAdvice class com.advice.UserDaoImpl, method.name : addUser , args : [com.smart.domain.User@71809907]
Add user
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章