隨筆-124  評論-49  文章-56  trackbacks-0
          AOP

          靜態(tài)代理
          通過接口實(shí)現(xiàn)

          動態(tài)代理

          1 編寫java代理類

          public class SecurityHandler implements InvocationHandler {
              
          private Object targetObject;
              
          //創(chuàng)建代理類
              public Object newProxy(Object targetObject){
                  
          this.targetObject=targetObject;
                  
          return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
                                                targetObject.getClass().getInterfaces(),
                                                
          this);
              }

              
          //
              public Object invoke(Object proxy, Method method, Object[] args)
                      
          throws Throwable {
                  checkSecurity();
                  Object result
          =null;
                  
          try {
                      result
          =method.invoke(this.targetObject, args);
                  }
           catch (RuntimeException e) {
                      
          // TODO Auto-generated catch block
                      e.printStackTrace();
                  }

                  
          return result;
              }

              
              
          private void checkSecurity(){
                  System.out.println(
          "------------checkSecurity-------------");
              }

          }
          2 調(diào)用
          SecurityHandler handler=new SecurityHandler();
              UserManager userManager
          =(UserManager)handler.newProxy(new UserManagerImpl());
              userManager.addUser(
          "張三""123456");
          ----------------------------------------------------------------------------------------------------------------------

          spring對AOP的支持(采用Annotation的方式)注解方式

          AOP:
             * Cross cutting concern 橫切性關(guān)注點(diǎn)
             * Aspect 切面,是對橫切性關(guān)注點(diǎn)的模塊化
             * Advice 橫切性關(guān)注點(diǎn)的實(shí)現(xiàn),切面的實(shí)現(xiàn)
             * Piontcut Advice應(yīng)用范圍的表達(dá)式
             * Joinpoint 執(zhí)行的點(diǎn),spring中是方法
             * Weave Advice

          1  spring的依賴庫
            * SPRING_HOME/dist/spring.jar
            * SPRING_HOME/lib/jakarta-commons/commons-logging.jar
            * SPRING_HOME/lib/log4j/log4j-1.2.14.jar
            * SPRING_HOME/lib/aspectj/*.jar(aspectjrt.jar/aspectjweaver.jar)
          ---applicationContext.xml

             <?xml version="1.0" encoding="UTF-8"?>
             
          <beans xmlns="http://www.springframework.org/schema/beans"
                 xmlns:xsi
          ="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:aop
          ="http://www.springframework.org/schema/aop"***************
                 xmlns:context
          ="http://www.springframework.org/schema/context"
                 xsi:schemaLocation
          ="http://www.springframework.org/schema/beans
                     http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                     http://www.springframework.org/schema/context
                     http://www.springframework.org/schema/context/spring-context-2.5.xsd
                     http://www.springframework.org/schema/aop       ****************
                     http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
          >****
              
          <context:annotation-config />//開啟配置項(xiàng)
              
          <aop:aspectj-autoproxy />

              
          <bean id="personDao" class="org.spring.dao.impl.PersonDaoImpl"/>
              
          </beans>
          2  采用Aspect定義切面,在Aspect定義Pointcut和Advice
              示例:
          @Aspect //切面
                  public class SecurityHandler  {
                      
          /**
                       * Pointcut,Pointcut的名稱就是allAddMethod,此方法不能有返回值和參數(shù),該方法只一個標(biāo)識
                       * Pointcut的內(nèi)容是一個表達(dá)式,描述那些對象的那些方法(訂閱Joinpoint)
                       * 定義
                       
          */

                      @Pointcut(
          "execution(* add*(..)) || execution(* del*(..))")
                      
          //@Pointcut("execution(* org.my.biz..*.*(..))")
                      private void allAddMethod(){};
                      
          /**
                       * 定義Advice,標(biāo)識在那個切入點(diǎn)何處織入些方法
                       
          */

                      @Before(
          "allAddMethod() && args(name)")//前置通知
                      [@AfterReturning("allAddMethod()")后置通知,可以同時存在]
                      [@After(
          "allAddMethod()")最終通知]
                      [AfterThrowing(
          "allAddMethod()")例外通知,拋異常時]
                      
          private void checkSecurity(String name){
                          System.out.println(
          "------------checkSecurity-------------");
                          System.out.println(name);
                      }

                      @Around(
          "allAddMethod()")//環(huán)繞通知
                      public Object doBasicProfiling(ProceedingJoinPiont pjp) throws Throwable{
                        
          if(){//判斷是否有權(quán)限
                          System.out.println("進(jìn)入方法");
                              Object result
          =pjp.proceed();//如果不調(diào)用這個方法,后面的業(yè)務(wù)bean及切面將不會執(zhí)行
                            }

                          
          return result;
                      }

                  }
          3  啟用Aspect對Annotation的支持并且將Aspect類和目標(biāo)對象配置到Ioc容器中
          <aop:aspectj-autoproxy />
             
          <bean id="securityHandler" class="com.my.spring.SecurityHandler"/>
               
          <bean id="userManager" class="com.my.spring.UserManagerImpl"/>
          4 調(diào)用
          BeanFactory factory=new ClassPathXmlApplicationContext("applicationContext.xml");
              UserManager userManager
          =(UserManager)factory.getBean("userManager");
            userManager.addUser(
          "張三""123456");
          注意:在這各方法定義中,切入點(diǎn)的方法是不被執(zhí)行的,它存在的目的僅僅是為了重用切入點(diǎn)
          即Advice中通過方法名引用這個切入點(diǎn)
          手動添加schema文件,方法如下:
          windows->preferences->myeclipse->files and editors->xml->xmlcatalog
          --------------------------------------------------------------------------------------------------

          spring對AOP的支持(采用配置文件的方式)

          Aspect默認(rèn)情況下不用實(shí)現(xiàn)接口,但對于目標(biāo)對象(UserManagerImpl.java),在默認(rèn)情況下必須實(shí)現(xiàn)接口,
          如查沒有實(shí)現(xiàn)接口必須引入CGLIB庫
          我們可以通過Advice中添加一個JoinPoint參數(shù),這個值會由spring自動傳入,從JoinPoint中可以取得能數(shù)值、方法名等等

          1  spring的依賴庫
            * SPRING_HOME/dist/spring.jar
            * SPRING_HOME/lib/jakarta-commons/commons-logging.jar
            * SPRING_HOME/lib/log4j/log4j-1.2.14.jar
            * SPRING_HOME/lib/aspectj/*.jar(aspectjrt.jar/aspectjweaver.jar)
          2  定義切面類

          public class SecurityHandler  {
                      
          private void checkSecurity(JoinPoint joinPoint){
                        Object[] args
          =joinPoint.getArgs();//得到參數(shù)集合
                        for(int i=0;i<args.length;i++){
                                System.out.println(args[i]);
                        }

                        System.out.println(joinPoint.getSignature().getName());
          //得到方法名
                          System.out.println("------------checkSecurity-------------");
                      }

                  }
          3  在配置文件中配置
             * xml方式
          <bean id="securityHandler" class="com.my.spring.SecurityHandler"/>
                  
          <bean id="userManager" class="com.my.spring.UserManagerImpl"/>
                  
          <aop:config>
                      
          <aop:aspect id="security" ref="securityHandler">
                          
          <aop:pointcut id="allAddMethod" expression="execution(* add*(..))"/>
                          
          <aop:before method="checkSecurity" pointcut-ref="allAddMethod"/>
          <!--
                          <aop:after method="checkSecurity" pointcut-ref="allAddMethod"/>
                          <aop:after-returning method="checkSecurity" pointcut-ref="allAddMethod"/>
                          <aop:after-throwing method="checkSecurity" pointcut-ref="allAddMethod"/>
                          <aop:around method="checkSecurity" pointcut-ref="allAddMethod"/>
          -->
                      
          </aop:aspect>
                  
          </aop:config>
          4  調(diào)用
          BeanFactory factory=new ClassPathXmlApplicationContext("applicationContext.xml");
                  UserManager userManager
          =(UserManager)factory.getBean("userManager");
                  userManager.addUser(
          "張三""123456");
          ---------------------------------------------------------------------------------------------------
          JDK動態(tài)代理和CGLIB
          手動編寫代碼:
          public class CGlibProxy implements MethodInterceptor{
              
          private Object targetObject;//代理目標(biāo)對象
              public Object createProxyIntance(Object targetObject){
                  
          this.targetObject=targetObject;
                  Enhancer enhancer
          =new Enhancer();//該類用于生成代理對象
                  
          //非final,繼承目標(biāo)類,并對非final方法進(jìn)行復(fù)蓋
                  enhancer.setSuperclass(this.targetObject.getClass());//設(shè)置父類
                  enhancer.setCallback(this);//設(shè)置回調(diào)用對象為本身
                  return enhancer.create();
              }

              @Override
              
          public Object intercept(Object proxy, Method mothod, Object[] args,
                      MethodProxy methodProxy) 
          throws Throwable {
                  PersonServiceBean bean
          =(PersonServiceBean)this.targetObject;
                  Object result
          =null;
                  
          if(bean.getUser()!=null){//判斷是否為空
                      result=methodProxy.invoke(targetObject, args);
                  }

                  
          return null;
              }

          }

          //test方法
          CGlibProxy cglibProxy=new CGlibProxy();
                  PersonServiceBean personServiceBean
          =(PersonServiceBean)cglibProxy.createProxyIntance(new PersonServiceBean());
                  personServiceBean.save(
          "dddddd");

          spring對AOP的支持
          1 如果目標(biāo)對象實(shí)現(xiàn)了接口,默認(rèn)情況下會采用JDK的動態(tài)代理實(shí)現(xiàn)AOP
          2 如果目標(biāo)對象實(shí)現(xiàn)了接口,可以強(qiáng)制使用CGLIB實(shí)現(xiàn)AOP
          3 如查目標(biāo)對象沒有實(shí)現(xiàn)接口,必須采用CGLIB庫,spring會自動在JDK動態(tài)代理和CGLIB之間轉(zhuǎn)換

          如何強(qiáng)制使用CGLIB實(shí)現(xiàn)AOP?
             * 添加CGLIB庫,在SPRING_HOME/cglib/*.jar
             * 在該spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
            
          JDK動態(tài)代理和CGLIB字節(jié)碼生成的區(qū)別:
            * JDK動態(tài)代理只能對實(shí)現(xiàn)了接口的類生成代理,而不能針對類
            * CGLIB是針對類實(shí)現(xiàn)代理,主要是對指定的類生成一個子類,覆蓋其中的方法
           因?yàn)槭抢^承,所以該類或方法最好不要聲明成final

          -------------------------------------------------------------------------------------------------------
          spring1.2 AOP實(shí)現(xiàn)方法
          1 advice類
          public class LogAdvice implements MethodBeforeAdvice {
              
          public void before(Method m, Object[] arg1, Object arg2)
                      
          throws Throwable {    
                  System.out.println(
          new Date()+"時間,調(diào)用了,"+m.getName()+"方法,參數(shù)為"+Arrays.toString(arg1));
              }

          }


          public class JiaAdvice implements AfterReturningAdvice {
              
          public void afterReturning(Object arg0, Method arg1, Object[] arg2,
                      Object arg3) 
          throws Throwable {
                  System.out.println(
          "給qian了");        
              }

          }
          2 biz類
          public class HelloBizImpl implements HelloBiz {
              
          public void say(String username) {
                  System.out.println(
          "歡迎你"+username);
              }

              
          public void sayHello(String word) {    
                  System.out.println(word);
              }

          }
          3 applicationContext.xml
          * 原始
          <!-- 定義實(shí)現(xiàn)類 -->
          <bean id="hellobiztarget"  class="org.somken.biz.impl.HelloBizImpl"/>
          <!-- 定義通知 -->
          <bean id="logAdvice" class="org.somken.advices.LogAdvice"/>
          <bean id="jiaAdvice" class="org.somken.advices.JiaAdvice"/>
          <!--aop-->
          <!--
          <bean id="hellobiz" class="org.springframework.aop.framework.ProxyFactoryBean">
              <property name="proxyInterfaces" value="org.somken.biz.HelloBiz" />
              <property name="interceptorNames">
                  <list>
                      <value>logAdvice</value>
                      <value>jiaAdvice</value>
                  </list>
              </property>
              
              <property name="target" ref="hellobiztarget" />
          </bean>
          -->
          * 結(jié)合
          <bean id="BaseBiz" abstract="true" class="org.springframework.aop.framework.ProxyFactoryBean">
              
          <property name="interceptorNames">
                  
          <list>
                      
          <value>logAdvice</value>
                  
          </list>
              
          </property>    
          </bean>

          <bean id="bookbiz" parent="BaseBiz">
              
          <property name="proxyInterfaces" value="org.somken.biz.ManagerBook" />
              
          <property name="target" ref="bookbiztarget"/>
          </bean>
          4 調(diào)用
          ApplicationContext  ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
          HelloBiz hellobiz
          =(HelloBiz)ctx.getBean("hellobiz");
          hellobiz.say(
          "劉德華");
          posted on 2009-11-30 08:36 junly 閱讀(350) 評論(0)  編輯  收藏 所屬分類: spring

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 托克逊县| 龙江县| 民和| 潼关县| 双流县| 郎溪县| 南宫市| 定安县| 科技| 海城市| 临猗县| 萍乡市| 溧阳市| 鹤壁市| 新宾| 江山市| 宝清县| 常熟市| 论坛| 赤峰市| 常山县| 奈曼旗| 白玉县| 开平市| 寿阳县| 中西区| 芦山县| 乾安县| 花莲县| 绥阳县| 松江区| 固原市| 来凤县| 宁安市| 万州区| 会泽县| 延边| 焉耆| 闽侯县| 林芝县| 扎囊县|