摘要:
|
“自立”是自然對每個人的要求.也許你的父母、老師能夠幫助你,其他人也可以幫助你,但是所有這些人都只是幫你更加自主、自立。
最近完結了有關於AOP相關知識的學習,接下來就給大家講講我對AOP的一些見解。
既然學習AOP大家知道AOP是什么嘛?那么就開始嘍~
AOP(Aspect Oriented Programming):面向切面編程,也是一種變成思想。(靜態角度)
OOP(Object Oriented Programming):面向對象編程。(動態代理:JDK動態代理 CGLIB動態代理)
代理模(Proxy):為其他對象提供一個代理以控制對這個對象的訪問。
適合的場合:遠程代理 虛擬代理 安全代理(只需要簡單了解不做詳解)
↑ ↑ ↑ ↑ ↑ ↑只是關於代理的圖片展示稍后會有詳細代碼
基本術語(一些名詞):
(1)切面(Aspect)
切面泛指[*交叉業務邏輯*]。事務處理和日志處理可以理解為切面。常用的切面有通知(Advice)與顧問(Advisor)。實際就是對主業務邏輯的一種增強。
(2)織入(Weaving)
織入是指將切面代碼插入到目標對象的過程。代理的invoke方法完成的工作,可以稱為織入。
(3) 連接點(JoinPoint)
連接點是指可以被切面織入的方法。通常業務接口的方法均為連接點
(4)切入點(PointCut)
切入點指切面具體織入的方法
注意:被標記為final的方法是不能作為連接點與切入點的。因為最終的是不能被修改的,不能被增強的。
(5)目標對象(Target)
目標對象指將要被增強的對象。即包含主業務邏輯的類的對象。
(6)通知(Advice)
通知是切面的一種實現,可以完成簡單的織入功能。通知定義了增強代碼切入到目標代碼的時間點,是目標方法執行之前執行,還是執行之后執行等。切入點定義切入的位置,通知定義切入的時間。
(7)顧問(Advisor)
顧問是切面的另一種實現,能夠將通知以更為復雜的方式織入到目標對象中,是將通知包裝為更復雜切面的裝配器。
Spring的經典AOP配置方案
1、使用的是Aspectj第三方框架,實現了AOP思想
2、注解配置的AOP
3、純POJO 就是一個普通的類<aop:config>
接下來進入代碼模式:
代碼模式一:純POJO(通過POJO來實現一個前置增強類)
定義一個簡單的UserBiz類給它一個方法:
1 package cn.happy.biz; 2 3 public class UserBiz { 4 public void addStu(UserInf user){ 5 System.out.println("add ok"); 6 } 7 }
在aop包下BeforeAdvice前置增強類,它需要實現MethodBeforeAdvice接口的before方法:
1 import org.springframework.aop.MethodBeforeAdvice; 2 3 /** 4 * before 5 * 6 */ 7 public class BeforeAdvice implements MethodBeforeAdvice{ 8 9 /** 10 * 11 * @param method 被代理的目標的方法 12 * @param args 傳遞給目標方法的參數 13 * @param obj 被代理的目標對象 14 15 * @throws Throwable 16 */ 17 @Override 18 public void before(Method method, Object[] args , Object obj) 19 throws Throwable { 20 System.out.println("========before======"); 21 }
配置文件(注意引入的命名空間)<aop:config>配置下實現切面:
1 ...... 2 <bean id="biz" class="cn.happy.biz.UserBiz"></bean> 3 4 <!-- 前置 --> 5 <bean id="beforeAdvice" class="cn.happy.aop.BeforeAdvice"></bean> 6 <!-- aop配置切面 --> 7 <aop:config> 8 <!-- 定義切點 --> 9 <aop:pointcut expression="execution(public void *(cn.happy.biz.UserInf))" id="pointcut"/> 10 <!-- 增強處理和切點結合 --> 11 <aop:advisor advice-ref="beforeAdvice" pointcut-ref="pointcut"/> 12 <aop:advisor advice-ref="afterAdivice" pointcut-ref="pointcut"/> 13 </aop:config> 14 ......
測試類:
1 public void testOne(){ 2 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); 3 UserBiz biz = (UserBiz)ctx.getBean("biz"); 4 biz.addStu(new UserInf()); 5 6 }
=========================華麗的分割線==================================
用注解配置的AOP:前置通知,后置通知,返回通知,異常通知,環繞通知
定義一個接口:
1 public interface ISomeService { 2 //1.1 執行事務 3 public void doTransaction(); 4 //1.2 書寫日志 5 public String doLog(); 6 }
實現接口的實現類:
1 public class SomeServiceImpl implements ISomeService { 2 3 public void doTransaction() { 4 System.out.println("開啟事務"); 5 } 6 7 public String doLog() { 8 System.out.println("書寫日志"+5/0); 9 return "我是書寫日志的返回值哦!!!!!"; 10 } 11 12 }
增強類用注解寫:
1 @Aspect 2 public class MyAspect { 3 //前置通知 4 @Before(value="execution(public * *(..))") 5 public void MyBefore(){ 6 System.out.println("這是前置通知哦!!!!!!!在執行目標對象之前執行"); 7 } 8 9 //后置通知 10 @AfterReturning(value="execution(public * *(..))") 11 public void MyAfterReturning(){ 12 System.out.println("這是后置通知哦!!!!!!!在執行目標對象之前執行"); 13 } 14 15 //環繞通知 16 /* @Around(value="execution(public * *(..))") 17 public void MyAround(ProceedingJoinPoint pjp){ 18 System.out.println("這是環繞通知前哦!!!!!!!在執行目標對象之前執行"); 19 try { 20 pjp.proceed(); 21 System.out.println("這是環繞通知后哦!!!!!!!在執行目標對象之前執行"); 22 } catch (Throwable e) { 23 // TODO Auto-generated catch block 24 e.printStackTrace(); 25 } 26 }*/ 27 28 //異常通知 29 @AfterThrowing(value="execution(public * *(..))") 30 public void MyAfterThrowing(){ 31 System.out.println("這是異常通知哦!!!!!!!在執行目標對象之前執行"); 32 } 33 34 //最終通知 35 @After(value="execution(public * *(..))") 36 public void MyAfter(){ 37 System.out.println("這是最終通知哦!!!!!!!在執行目標對象之前執行"); 38 } 39 }
配置文件:
1 <!-- 目標對象 --> 2 <bean id="someService" class="cn.happy.enetity.SomeServiceImpl"></bean> 3 4 <!-- 切面: --> 5 <bean id="myAspect" class="cn.happy.aspece.MyAspect"></bean> 6 <!--aop:aspectj可以啟動對@AspectJ注解支持--> 7 <aop:aspectj-autoproxy/> 8 </beans>
測試類:
1 public void testOne(){ 2 3 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); 4 ISomeService service = (ISomeService)ctx.getBean("someService"); 5 service.doTransaction(); 6 String result = service.doLog(); 7 System.out.println(result); 8 }
=========================華麗的分割線==================================
使用的是Aspectj第三方框架,實現了AOP思想XML的方式(就是一個普通類通過配置實現 )
定義一個接口:
1 public interface ISomeService { 2 //1.1 執行事務 3 public void doTransaction(); 4 //1.2 書寫日志 5 public String doLog(); 6 }
實現類:
1 public class SomeServiceImpl implements ISomeService { 2 3 public void doTransaction() { 4 System.out.println("開啟事務"); 5 } 6 7 public String doLog() { 8 /*System.out.println("書寫日志"+5/0);*/ 9 System.out.println("書寫日志"); 10 return "我是書寫日志的返回值哦!!!!!"; 11 } 12 13 }
定一個增強類就是一個普通類通過配置實現 :
1 public class MyAspect { 2 // 前置通知execution(public * *(..)) 3 public void MyBefore() { 4 System.out.println("這是前置通知哦!!!!!!!在執行目標對象之前執行"); 5 } 6 7 // 后置通知execution(public * *(..)) 8 public void MyAfterReturning() { 9 System.out.println("這是后置通知哦!!!!!!!在執行目標對象之前執行"); 10 } 11 12 // 異常通知 13 public void MyAfterThrowing() { 14 System.out.println("這是異常通知哦!!!!!!!在執行目標對象之前執行"); 15 } 16 17 // 最終通知 18 public void MyAfter() { 19 System.out.println("這是最終通知哦!!!!!!!在執行目標對象之前執行"); 20 } 21 22 //環繞通知 23 public String MyAround(ProceedingJoinPoint pjp){ 24 System.out.println("這是環繞通知前哦!!!!!!!在執行目標對象之前執行"); 25 try { 26 Object result=pjp.proceed(); 27 System.out.println("這是環繞通知后哦!!!!!!!在執行目標對象之前執行"); 28 } catch (Throwable e) { 29 // TODO Auto-generated catch block 30 e.printStackTrace(); 31 } 32 return "result"; 33 } 34 }
配置文件:
1 ...... 2 <!-- 目標對象 --> 3 <bean id="someService" class="enetity.SomeServiceImpl"></bean> 4 5 <!-- 切面: --> 6 <bean id="myAspect" class="aspece.MyAspect"></bean> 7 8 9 <!-- aop的配置 --> 10 <aop:config> 11 <!-- 切點 --> 12 <aop:pointcut expression="execution(public * *(..))" id="dopointcut"/> 13 <aop:aspect ref="myAspect"> 14 15 <aop:before method="MyBefore" pointcut-ref="dopointcut"/> 16 <aop:after-returning method="MyAfterReturning" pointcut-ref="dopointcut"/> 17 <!-- <aop:after-throwing method="MyAfterThrowing" pointcut-ref="dopointcut"/> --> 18 <aop:after method="MyAfter" pointcut-ref="dopointcut"/> 19 <aop:around method="MyAround" pointcut-ref="dopointcut"/> 20 </aop:aspect> 21 22 </aop:config> 23 </beans> 24 ......
測試類:
1 public void testOne(){ 2 3 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); 4 ISomeService service = (ISomeService)ctx.getBean("someService"); 5 service.doTransaction(); 6 String result = service.doLog(); 7 System.out.println(result); 8 }
以上就是我對AOP相關知識代碼層面的講解。學的不是很好,也是早上請教了同學才能更深一層了解AOP。就如文章開頭:
“自立”是自然對每個人的要求.也許你的父母、老師能夠幫助你,其他人也可以幫助你,但是所有這些人都只是幫你更加自主、自立。
希望可以鼓勵那些在快學不下去的時候去請教下同學,老師...