Spring aop 配置和註解及詳解
Spring aop
aop:(Aspect Oriented Programming)面向切面程式設計,縱向重複,橫向抽取
代理: 生活中的例項:找明星拍戲,上綜藝。拍戲 直接找明星,說明明星太小。如果明星有點名氣,那就不能直接訪問了,必須先通過先訪問明星的經紀人,然後由經紀人訪問明星,經紀人就是明星的代理。放在程式當中,有一個目標物件,一個代理物件, 你想訪問目標物件,必須訪問代理物件,由代理物件決定訪問目標物件。Java 中提供了一個類Proxy 能夠實現代理
Spring AOP
利用了代理技術 主要應用於在service層的事務管理
Spring實現aop 有兩種方法
(1)動態代理(建議):被代理物件必須實現介面,如果沒有介面則不能實現動態代理
(2)cglib代理: 第三方的代理技術。任何類都可以實現代理,使用繼承的機制實現代理,所以被代理物件不能被final修飾
手動實現 動態代理
準備一個UserService UserServiceImpl
準備獲得UserService代理物件的類
1. 獲取代理物件 通過呼叫Proxy 的new ProxyInstance方法 創第三個引數(1本類的載入器,2代理物件的介面(實現類獲得介面),3this),這樣就得到了一個代理物件
2. 實現代理物件的方法 讓這個類 實現InvocationHandler介面 實現了它的方法 invoke(代理的物件,呼叫的方法,方法的的引數)
被代理的物件方法還是要被呼叫,所有呼叫method,invoke()兩個引數,一個是被代理的物件,引數 給該類加上一個屬性被代理物件,並給該類新增建構函式,在呼叫被代理物件方法的前後 可以加上對應的內容
public class UserServiceProxyFactory implements InvocationHandler{private UserService userService;public UserServiceProxyFactory(UserService userService) {this.userService = userService; }public UserService getUserServiceProxy(){ |
cglib代理
public class UserServiceProxyFactory2 implements MethodInterceptor{public UserService getUserServiceProxy(){ Enhancer enhancer = new Enhancer();//幫助我們生成代理物件enhancer.setSuperclass(UserServiceImpl.class);//設定對誰進行代理enhancer.setCallback(this); //回撥方法UserService userServiceProxy = (UserService) enhancer.create(); //生成一個代理物件return userServiceProxy; }@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("開啟事務"); Object o1 = methodProxy.invokeSuper(o, objects);//(被代理物件,方法引數)System.out.println("關閉事務");return o1; }} |
Spring AOP 配置
7個專業名詞
JoinPoint (連線點)
1. 導包
4+2 + 2+2 spring(aop aspect) spring依賴包()
2. 準備目標物件 UserServiceImpl
3. 準備通知
4. 配置applicationContext.xml檔案
匯入約束:
直接打入<aop:conf 如果有提示 直接打回車 自動幫你匯入約束
沒有的話 就手動匯入
xmlns:aop="http://www.springframework.org/schema/aop" <!--配置aop切入--><aop:config></aop:config> |
配置切入:
1. 配置切入點
<aop:pointcut id=”” expreession=”” 目標物件要增強的方法</aop:pointcut> |
2. 配置切面: 將通知織入到對應的切入點
<aop:aspect ref="通知"></aop:aspect> |
多種方式切入
總共有五種切入方式
1. 在目標物件方法前呼叫
<aop:before method="before" pointcut-ref="pc"></aop:before> |
2. 在目標物件方法後呼叫(沒有異常,有異常不呼叫)
<aop:after-returning method="afterReturning" pointcut-ref="pc"></aop:after-returning> |
3. 在目標物件方法後(不管啊有無異常)
<aop:after method="after" pointcut-ref="pc"></aop:after> |
4. 在目標物件方法前後呼叫程式碼(特殊,在通知中的方法)
ProceedingJoinPoint(引數)如果有異常方法後不呼叫
<aop:around method="around" pointcut-ref="pc"></aop:around> |
5. 只在目標物件方法出現異常時呼叫
<aop:after-throwing method="throwException" pointcut-ref="pc"></aop:after-throwing> |
<!--引入切入點 寫那個類中的方法程式碼塊--><aop:beforemethod="通知中增強的程式碼" pointcut-ref="切入點"></aop:before> |
實現程式碼:
<aop:config><!--配置切入點 proxy-target-class="true" 基於類的代理將起作用 --> |
使用註解的方式配置AOP(瞭解)
1. 開啟註解模式
<!--開啟註解模式--><aop:aspectj-autoproxy></aop:aspectj-autoproxy> |
2. 註解切面
再通知上面加上一個註解 @ Aspect
再通知的方法上面加上切點
五種:
@Before(表示式) @After @AfterReturning @Around @AfterThrowing
@Before("execution(* cn.hd.springProxyAnnotation.impl.UserServiceImpl.*(..))")public void before(){ System.out.println("在目標物件方法前呼叫"); } |
書寫表達方式有兩種
1. 直接寫
@Before("execution(* cn.hd.springProxyAnnotation.impl.UserServiceImpl.*(..))")public void before(){ System.out.println("在目標物件方法前呼叫"); } |
2. 配置一個切點 呼叫類的方法獲得切點
public class MyAdvice {@Pointcut("execution(* cn.hd.springProxyAnnotation.impl.UserServiceImpl.*(..))")public void pc(){ } } @AfterReturning("MyAdvice.pc()")public void afterReturning(){ System.out.println("如果目標物件方法嗎沒有出現異常"+"就會在該方法呼叫後呼叫");} |