AOP:面向切面、面向方面、面向接口是一種橫切技術
橫切技術運用:
1.事務管理: (1)數據庫事務:(2)編程事務(3)聲明事物:Spring AOP-->聲明事物
2.日誌處理:
3.安全驗證: Spring AOP---OOP升級
html
靜態代理原理:目標對象:調用業務邏輯 代理對象:日誌管理
表示層調用--->代理對象(日誌管理)-->調用目標對象java
動態代理原理:spring AOP採用動態代理來實現
(1)實現InvocationHandler接口程序員
(2)建立代理類(經過java API)spring
Proxy.newProxyInstance(動態加載代理類,代理類實現接口,使用handler);數據庫
(3)調用invoke方法(虛擬機自動調用方法)express
日誌處理
//調用目標對象
method.invoke("目標對象","參數");
日誌處理編程
經過代理對象--(請求信息)-->目標對象---(返回信息)----> 代理對象安全
Spring 動態代理中的基本概念app
一、關注點(concern)
一個關注點能夠是一個特定的問題,概念、或者應用程序的興趣點。總而言之,應用程序必須達到一個目標
安全驗證、日誌記錄、事務管理都是一個關注點
在oo應用程序中,關注點可能已經被代碼模塊化了還可能散落在整個對象模型中
二、橫切關注點(crosscutting concern)
如何一個關注點的實現代碼散落在多個類中或方法中
三、方面(aspect)
一個方面是對一個橫切關注點模塊化,它將那些本來散落在各處的,
用於實現這個關注點的代碼規整在一處
四、建議(advice)通知
advice是point cut執行代碼,是方面執行的具體實現
五、切入點(pointcut)
用於指定某個建議用到何處
六、織入(weaving)
將aspect(方面)運用到目標對象的過程
七、鏈接點(join point)
程序執行過程當中的一個點 ide
通知類型:
try{
//前置通知
//環繞通知
//調用目標對象方法
//環繞通知
//後置通知
}catch(){
//異常通知
}finally{
//終止通知
}
流程圖
![](http://static.javashuo.com/static/loading.gif)
一.靜態代理原理實例:
項目結構圖:
![](http://static.javashuo.com/static/loading.gif)
IUserServ接口代碼
- public interface IUserServ {
- List<User> findAllUser();
- int deleteUserById(User user);
- int saveUser(User user);
- }
UserServImpl實現類代碼
- public class UserServImpl implements IUserServ {
- public int deleteUserById(User user) {
- System.out.println("******執行刪除方法******");
- return 0;
- }
- public List<User> findAllUser() {
- System.out.println("*******執行查詢方法*******");
- return null;
- }
- public int saveUser(User user) {
- System.out.println("*******執行添加方法********");
- return 0;
- }
- }
UserServProxyImpl實現類代碼
- public class UserServProxyImpl implements IUserServ {
-
-
-
- private IUserServ iuserServ ;
-
- public UserServProxyImpl(IUserServ iuserServ){
- this.iuserServ = iuserServ;
- }
- public int deleteUserById(User user) {
- beforeLog();
-
- iuserServ.deleteUserById(user);
- afterLog();
- return 0;
- }
-
- public List<User> findAllUser() {
- beforeLog();
-
- iuserServ.findAllUser();
- afterLog();
- return null;
- }
-
- public int saveUser(User user) {
- beforeLog();
-
- iuserServ.saveUser(user);
- afterLog();
- return 0;
- }
-
- private void beforeLog() {
- System.out.println("開始執行");
- }
-
- private void afterLog() {
- System.out.println("執行完畢");
- }
- }
ActionTest測試類代碼
- public class ActionTest {
- public static void main(String[] args) {
-
- IUserServ iuserServ = new UserServProxyImpl(new UserServImpl());
- iuserServ.findAllUser();
- }
- }
運行結果:
開始執行
*******執行查詢方法*******
執行完畢
二.動態代理實例
項目結構圖:
![](http://static.javashuo.com/static/loading.gif)
IUserServ接口代碼與UserServImpl實現類代碼和上述代碼相同
LogHandler類代碼
- public class LogHandler implements InvocationHandler {
-
- private Object targetObject;
-
- public Object createProxy(Object targetObject){
- this.targetObject = targetObject;
- return Proxy.newProxyInstance(
- targetObject.getClass().getClassLoader(),
- targetObject.getClass().getInterfaces(), this);
- }
- @Override
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- Object obj = null;
- try {
- beforeLog();
-
-
-
- obj = method.invoke(targetObject, args);
- afterLog();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return obj;
- }
-
-
- private void beforeLog(){
- System.out.println("開始執行");
- }
-
- private void afterLog(){
- System.out.println("執行完畢");
- }
-
- }
ActionTest測試類代碼:
- public class ActionTest {
- public static void main(String[] args) {
-
- LogHandler handler = new LogHandler();
- IUserServ iuserServ = (IUserServ)handler.createProxy(new UserServImpl());
- iuserServ.deleteUserById(new User());
- }
- }
運行結果:
開始執行
******執行刪除方法******
執行完畢
三.Spring AOP使用(2.x版本以前)
項目結構圖:
![](http://static.javashuo.com/static/loading.gif)
IUserServ接口代碼與UserServImpl實現類代碼和上述代碼相同
配置步驟:
一、配置目標對象(applicationContext.xml)
- <bean id="userServTarget" class="com.tarena.biz.impl.UserServImpl"/>
二、配置通知
(a)前置通知(BeforeLogAdvice)
- public class BeforeLogAdvice implements MethodBeforeAdvice {
-
- public void before(Method method, Object[] args, Object target)
- throws Throwable {
- beforeLog();
- }
- private void beforeLog(){
- System.out.println("開始執行");
- }
- }
(b)後置通知(AfterLogAdvice)
- public class AfterLogAdvice implements AfterReturningAdvice {
-
- public void afterReturning(Object returnValue, Method method,
- Object[] args, Object target) throws Throwable {
- afterLog();
- }
- private void afterLog(){
- System.out.println("執行完畢");
- }
- }
(c)在spring容器中,讓容器管理通知(applicationContext.xml)
-
- <bean id="beforeLogAdvice" class="com.tarena.advice.BeforeLogAdvice"/>
-
- <bean id="afterLogAdvice" class="com.tarena.advice.AfterLogAdvice"/>
三、配置代理對象(applicationContext.xml)
- <bean id="userServProxy"
- class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="interfaces">
-
- <list>
- <value>com.tarena.biz.IUserServ</value>
- </list>
- </property>
-
- <property name="interceptorNames">
- <list>
- <value>beforeLogAdvice</value>
- <value>afterLogAdvice</value>
- </list>
- </property>
-
- <property name="target" ref="userServTarget"/>
- </bean>
4.訪問()
Spring容器:經過代理對象調用-->織入通知--->目標對象
程序員:訪問代理對象
測試類(ActionTest):
- public class ActionTest {
- public static void main(String[] args) {
- ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
- IUserServ iuserServ = (IUserServ)ac.getBean("userServProxy");
- iuserServ.deleteUserById(new User());
- iuserServ.findAllUser();
- }
- }
運行結果:
開始執行
******執行刪除方法******
執行完畢
開始執行
*******執行查詢方法*******
執行完畢
四.Spring AOP使用(2.x版本以後)這種方式須要額外添加兩個jar包,
存放位置在spring-framework-2.5.6.SEC01\lib\aspectj文件夾下。
項目結構圖
![](http://static.javashuo.com/static/loading.gif)
IUserServ接口代碼與UserServImpl實現類代碼和上述代碼相同
LogAdvice中
- public class LogAdvice {
- public void beforeLog(){
- System.out.println("開始執行");
- }
- public void afterLog(){
- System.out.println("執行完畢");
- }
- }
applicationContext.xml中
-
- <bean id="userServImpl" class="com.tarena.biz.impl.UserServImpl"/>
-
- <bean id="logAdvice" class="com.tarena.advice.LogAdvice"/>
-
- <aop:config>
- <aop:aspect id="logAspect" ref="logAdvice">
-
- <aop:pointcut id="beforePointCut"
- expression="execution(* saveUser*(..))"/>
- <aop:pointcut id="afterPointCut"
- expression="execution(* saveUser*(..))"/>
-
-
- <aop:before method="beforeLog" pointcut-ref="beforePointCut"/>
- <aop:after method="afterLog" pointcut-ref="afterPointCut"/>
- </aop:aspect>
- </aop:config>
測試類:
- public class ActionTest {
- public static void main(String[] args) {
- ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
- IUserServ iuserServ = (IUserServ)ac.getBean("userServImpl");
- iuserServ.deleteUserById(new User());
- iuserServ.findAllUser();
- iuserServ.saveUser(new User());
- }
- }
運行結果
******執行刪除方法******
*******執行查詢方法*******
開始執行
*******執行添加方法********
執行完畢
注:若是要在業務層全部的方法先後添加日誌文件,則須要更改成如下配置
- <aop:pointcut id="beforePointCut"
- expression="execution(* com.tarena.biz.*.*(..))"/>
- <aop:pointcut id="afterPointCut"
- expression="execution(* com.tarena.biz.*.*(..))"/>
運行結果:
開始執行******執行刪除方法******執行完畢開始執行*******執行查詢方法*******執行完畢開始執行*******執行添加方法********執行完畢