1. 程式人生 > >Spring aop 配置和註解及詳解

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(){

        UserService userServiceProxy = (UserService) Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(),                UserServiceImpl.class.getInterfaces(), this);return userServiceProxy; //使用者服務代理}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("開啟事務");//呼叫了代理物件(UserService)的方法Object invoke = method.invoke(userService, args);        System.out.println("關閉事務");return invoke;    }}

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  springaop aspectspring依賴包()

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"  基於類的代理將起作用
       proxy-target-class="false"     基於介面的代理將起作用
   如果目標物件沒有實現介面,則預設會採用CGLIB代理;
 如果目標物件實現了介面,可以強制使用CGLIB實現代理。

-->
    <!--
        public void cn.hd.springProxy.impl.UserServiceImpl.add()
                *  cn.hd.springProxy.impl.UserServiceImpl.add() //public可以省略  返回值可以是是任意型別*號代替
                *  cn.hd.springProxy.impl.*ServiceImpl.*(..)
                //所有方法可以用 * 所有引數可以用.. 所有Service  可以 *ServiceImpl
                *  cn.hd.springProxy.impl..*ServiceImpl.*(..)
    -->
<aop:pointcut id="pc" expression="execution(* cn.hd.springProxy.impl.*ServiceImpl.*(..))"></aop:pointcut><!--配置切面 織入通知-->
<aop:aspect ref="myAdvice"><!--引入切入點 寫那個類中的方法程式碼塊-->
<aop:before method="before" pointcut-ref="pc"></aop:before></aop:aspect></aop:config>

使用註解的方式配置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("如果目標物件方法嗎沒有出現異常"+"就會在該方法呼叫後呼叫");}