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