實現原理:
前置增強完成功能:在目標類的方法執行之前嵌入增強邏輯.
實現原理:
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