Java Web學習(八)

AOP的應用場合是受限的,它通常只適合於那些具備橫切邏輯的應用場合:性能檢測,訪問控制、事務管理,日誌記錄等java

  1. AOP是什麼?正則表達式

    Aspect Oriented Programming。面向方面編程。spring

    一些重複代碼沒法經過縱向繼承(即抽象父類)的方式來消除,AOP提供了一種解決這類沒法經過縱向編程解決的問題的方法,即經過橫向抽取機制。編程

  2. AOP概念性能

    ①鏈接點(JoinPoint)spa

    一個類或一段程序代碼擁有一些具備邊界性質的特定點,這些代碼中的特定點稱爲鏈接點。鏈接點由兩個信息肯定,第一爲用方法表示的程序執行點,第二是用相對點表示的方位。代理

    ②切點(PointCut)日誌

    一個類中有多個鏈接點,如何定位到某一個特定的鏈接點呢?AOP經過切點來定位鏈接點。切點只定位到某個方法上,具體的方位還不能肯定.code

    ③加強(Advice)regexp

    加強是織入到目標類鏈接點上的一段代碼。加強除了用來描述一段程序代碼外,還擁有鏈接點的方位、

    只有結合切點和加強纔可以肯定特定的鏈接點並實施加強邏輯。

    ④目標對象(Target)

    加強邏輯的織入目標類

    ⑤引入(Introduction)

    引入是一種特殊的加強。它爲類添加一些屬性和方法。即即便一個業務類沒有實現某個接口,經過AOP的引入功能,能夠動態地爲該業務類添加接口的實例邏輯,讓業務類成爲這個接口的實現類。

    ⑥織入(Weaving)

    織入是將加強添加到目標類具體鏈接點上的過程。AOP由三種織入的方式:編譯器織入,類裝載器織入,動態代理織入。

    ⑦代理(Proxy)

    一個類被AOP織入加強後,就產生一個結果類,它是融合了原類和加強邏輯的代理類。代理類多是與原類實現相同接口的類,也可能就是原類的子類。因此能夠以調用原類相同的方法來調用代理類。

    ⑧切面(Aspect)

    切面由切點和加強組成,它既包括了橫切邏輯的定義,也包括了鏈接點的定義。AOP將切面所定義的橫切邏輯織入到切面定義的鏈接點中。

  3. 經過建立加強類的方式來實現AOP

    步驟:①首先建立加強類,經過實現某個接口(BeforeAdvice, AfterReturningAdvice, MethodInterceptor, ThrowsAdvice, IntroductionInterceptor)來實現一個加強邏輯類。

             ②在Spring配置文件中進行配置。首先配置一個Advice Bean和目標對象Bean,而後建立一個代理Bean(ProxyFactoryBean),在代理Bean中配置interfaces。target,advice等等屬性;

             ③獲得代理Bean,調用業務方法。

    ①定義一個接口
    public interface Waiter {
         void greetTo(String name);
        void serveTo(Sring name);
    }
    ②實現此接口
    public class MyWaiter implements Waiter {
         public void greetTo(String name){
              System.out.println("hello!"+name);
        }
        
        public void serveTo(String name){
              System.out.println("serving"+name);
         }
    } 
    ③建立加強類
    public class GreetingBeforeAdvice implements MethodBeforeAdvice {
         public void before(Method method, Object[] args, Object obj){
              String name = (String) args[0];
             System.out.println("before " + name);
         }
     }
     
    ④配置AOP
    <bean id="beforeAdvice" class="GreetingBeforeAdvice"/>
    <bean id="target" class="MyWaiter"/>
    <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean">
          <property name="proxyInterfaces" value="Waiter"/>
          <property name="interceptorNames">
               <list>
                     <idref local="beforeAdvice"/>
              </list>
          </property>
         <property name="target" ref="target"/>
    </bean>
    ⑤調用業務方法     
    Waiter waiter = (Waiter) ctx.getBean("waiter");
    waiter.greetTo("kaka");

    ProxyFactoryBean爲其餘Bean建立代理實例。它的可配置屬性有target、proxyInterfaces、interceptorNames、singleton、optimize。proxyTargetClass(設置爲true是使用CGLib進行代理)

    說明:public void before(Method method, Object[] args, Object obj)中method爲要加入加強邏輯的方法,args爲方法入參,obj爲代理目標對象

    public void afterReturning(Method method, Object[] args, Object obj)、

    Object invoke(MethodInvocation invocation) { Object[] args = invocation.getArguments(); Object resuld = invocation.proceed();}

    public void afterThrowing(Method method, Object[] args, Object obj, Exception ex)

    比較特殊的一個是引入加強。他不是在目標方法周圍織入加強,而是爲目標類建立新的屬性或方法,因此引入加強的鏈接點是類級別的,而非方法級別的。通常經過擴展DelegatingIntroductionInterceptor類。

    定義一個接口
    public interface Monitor {
        void setMonitorActive(boolean active);
    }
    定義一個引入加強類
    public class IntroductionAdvice extends DelegatingIntrodutionInterceptor implements Monitor {
           private ThreadLocal<Boolean> map = new ThreadLocal<>();
         
          public void setMonitorActive(boolean active){
                   map.set(active);
            }
            
            public Object invoke(MethodInvocation invocation){
                  Object obj = null;
                  if(map.get()){
                        begin();
                       obj = super.invoke(invocation);
                       end();
                  }else{
                        obj = super.invoke(invocation);
                  }
                  return obj;
             }
     }
     
     配置引入加強
     
    <bean id="introductionAdvice" class="IntroductionAdvice"/>
    <bean id="target" class="MyWaiter"/>
    <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean">
          <property name="interfaces" value="...Monitor"/>
          <property name="interceptorNames">
               <list>
                     <idref local="beforeAdvice"/>
              </list>
          </property>
         <property name="target" ref="target"/>
         <property name="proxyTargetClass" value="true"/>
    </bean>
    調用業務方法
    Waiter waiter = (Waiter) ctx.getBean("waiter");
    waiter.greetTo("kaka");
    Monitor monitor = (Monitor) waiter;
    monitor.setMonitorActive(true);
    monitor.greetTo("kaka")
  4. 經過建立切面(Aspect)的方式來實現AOP

    切面同時包含橫切代碼和鏈接點信息。切面可分爲三類:通常切面,切點切面,引入切面

     ‍      PointcutAdvisor有6個主要的實現類:DefaultPointcutAdvisor, NameMatchMethodPointcutAdvisor, RegexpMethodPointcutAdvisor, StaticMethodMatcherPointcutAdvisor, AspectJExpressionPointcutAdvisor, AspectJPointcutAdvisor。

    ①靜態方法名匹配切面

    步驟:1)定義目標類; 2)定義切面; 3)定義加強類;4)配置切面;5)運行業務代碼 

    public class GreetingAdvisor extends StaticMethodMatcherPointcutAdvisor {
          public bolean matches(Method method, Class clazz){
               return "greetTo".equals(method.getName());
          }
          
          public ClassFilter getClassFilter(){
               return new ClassFilter(){
                     public boolean matches(Class clazz){
                           return Waiter.class.isAssignable(clazz);
                     }
              };
          }
    }      
    配置
    <bean id="target" class="MyWaiter"/>
    <bean id="beforeAdvice" class="GreetingBeforeAdvice"/>
    <bean id="beforeAdvisor" class="GreetingAdvisor"/>
            <property name="advisor" ref="beforeAdvice"/>
    </bean>
    <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean">
          <property name="interceptorNames">
               <list>
                     <idref local="beforeAdvisor"/>
              </list>
          </property>
          <property name="target" ref="target"/>
          <property name="targetProxyClass" value="true"/>
    </bean>

    ②靜態正則表達式方法匹配切面

    只需配置便可

    <bean id="beforeAdvice" class="GreetingBeforeAdvice"/>
    <bean id="regexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
          <property name="patterns">
                <list>
                     <value>.*greet.*</value>
                </list>
          </proerty>
          <property name="advice" ref="beforeAdvice"/>
    </bean>
    <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean">
          <property name="interceptorNames">
               <list>
                     <idref local="regexpAdvisor"/>
              </list>
          </property>
          <property name="target" ref="target"/>
         <property name="targetProxyClass" value="true"/>
    </bean>

     

  5. 自動建立代理

    在前面的例子中,咱們經過PRoxyFactoryBean建立織入切面的代理,但每個須要被代理的Bean都須要一個單獨的PRoxyFactoryBean進行配置,這樣配置非常麻煩。因此Spring引入了自動代理機制,讓容器爲咱們自動生成代理,將咱們從繁瑣的配置工做中解放出來。在內部,Spring用BeanPostProcessor自動的完成這項工做。

    ①實現類

    基於BeanPostProcessor的自動建立器的實現類,將根據一些規則自動的在容器實例化Bean時爲匹配的Bean生成代理實例。

    這些代理建立器能夠分爲一下三類:

    ~根據Bean配置名規則的自動代理建立器,BeanNameAutoProxyCreator

    ~基於Advisor匹配機制的自動代理建立器 DefaultAdvisorAutoProxyCreator

    ~基於Bean中AspectJ註解標籤的自動代理建立器 AnnotatiobAwareAspectJAutoProxyCreator

    ②使用Bean名進行自動代理

    <bean id="beforeAdvice" class="GreetingBeforeAdvice"/>
    <bean id="nameCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
           <property name="beanNames" value="*er"/>
          <property name="interceptorNames">
               <idref local="beforeAdvice"/>
          </property>
    </bean>

    ③使用Advisor自動代理建立器

    由於Advisor切面已經包括了鏈接點信息和橫切邏輯,因此直接而配置一自動代理建立器便可

<bean id="beforeAdvice" class="GreetingBeforeAdvice"/>

<bean id="regexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

      <property name="patterns">

            <list>

                 <value>.*greet.*</value>

            </list>

      </proerty>

      <property name="advice" ref="beforeAdvice"/>

</bean>

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

 

相關文章
相關標籤/搜索