面向方面編程。spring
ProxyFactoryBean是FactoryBean接口的實現類。FactoryBean負責實例化一個Bean,編程
即app
<bean id="logAdvice" class="com.xue.aop.LogAdvice"></bean>
而ProxyFactoryBean負責建立代理實例,他內部使用FactoryBean來完成這一工做。使用這個是建立AOP的最基本的方式。
例如:
數據訪問層:
項目的Userao接口中聲明兩個方法
public interface UserDao { public void addUser(String username,String password); public void delUser(int id); }
UserDao的實現類:ide
public class UserDaoImpl implements UserDao { @Override public void addUser(String username, String password) { System.out.println(username+"用戶添加成功"); } @Override public void delUser(int id) { System.out.println("編號爲"+id+"的用戶被刪除"); } }
業務邏輯層:測試
在UserBiz中,聲明兩個方法:this
public interface UserBiz { public void addUser(String username, String passworld); public void delUser(int id); }
UserBiz的實現類:spa
public class UserBizImpl implements UserBiz { UserDao userDao; //set方法用於依賴注入 public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void addUser(String username, String passworld) { userDao.addUser(username,passworld); } @Override public void delUser(int id) { userDao.delUser(id); } }
方面代碼:代理
實現特定功能的方面代碼在AOP概念中被稱爲「通知(Advice)」。通知分爲前置通知、後置通知、環繞通知和異常通知。日誌
前置通知:(log4j的配置不作介紹)code
public class LogAdvice implements MethodBeforeAdvice { private Logger logger=Logger.getLogger(LogAdvice.class); @Override public void before(Method method, Object[] args, Object target) throws Throwable { //獲取被調用的類名 String targetClassname=target.getClass().getName(); //獲取被調用的方法名 String targetMethodname=method.getName(); String logInfoText="前置通知:"+targetClassname+"類的"+targetMethodname+"方法開始執行"; logger.info(logInfoText); } }
配置ApplicationContext.xml文件:
<bean id="userDao" class="com.xue.dao.UserDaoImpl"></bean> <bean id="userBiz" class="com.xue.dao.UserBizImpl"> <property name="userDao" ref="userDao"></property> </bean> <bean id="logAdvice" class="com.xue.aop.LogAdvice"></bean> <!--使用spring代理工廠定義一個代理,經過他訪問業務類中的方法--> <bean id="ub" class="org.springframework.aop.framework.ProxyFactoryBean"> <!--指定代理接口--> <property name="proxyInterfaces"> <value>com.xue.dao.UserBiz</value> </property> <!--指定通知--> <property name="interceptorNames"> <list> <value>logAdvice</value> </list> </property> <!--指定目標對象--> <property name="target" ref="userBiz"></property> </bean>
測試類:
public class Test { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); UserBiz userBiz= (UserBiz) context.getBean("ub"); userBiz.addUser("zhangsan","123"); userBiz.delUser(1); } }
總結:雖然沒有看過源碼,但我的感受,測試類中UserBiz經過getBean(「ub」)獲取實例,是ProxyFactoryBean會自動在配置的xml中返回實例,而且讓指定的通知在方法執行前執行。
LogAdvice(指定的通知)作的事:獲取類名、方法名,將其寫入日誌中。
結果:
[INFO ] [18:02:32] com.xue.aop.LogAdvice - 前置通知:com.xue.dao.UserBizImpl類的addUser方法開始執行zhangsan用戶添加成功[INFO ] [18:02:32] com.xue.aop.LogAdvice - 前置通知:com.xue.dao.UserBizImpl類的delUser方法開始執行編號爲1的用戶被刪除