Spring AOP(1)- 前置增强 实现

本文介绍如何在Spring框架中实现前置增强功能,通过实现MethodBeforeAdvice接口并在UserDaoImpl类的方法前插入自定义逻辑。文章详细展示了如何配置Spring XML来使用代理工厂或AOP动态代理。
摘要由CSDN通过智能技术生成

实现原理:

前置增强完成功能:在目标类的方法执行之前嵌入增强逻辑.
实现原理:
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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值