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

          靜態代理
          通過接口實現

          動態代理

          1 編寫java代理類

          public class SecurityHandler implements InvocationHandler {
              
          private Object targetObject;
              
          //創建代理類
              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 調用
          SecurityHandler handler=new SecurityHandler();
              UserManager userManager
          =(UserManager)handler.newProxy(new UserManagerImpl());
              userManager.addUser(
          "張三""123456");
          ----------------------------------------------------------------------------------------------------------------------

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

          AOP:
             * Cross cutting concern 橫切性關注點
             * Aspect 切面,是對橫切性關注點的模塊化
             * Advice 橫切性關注點的實現,切面的實現
             * Piontcut Advice應用范圍的表達式
             * Joinpoint 執行的點,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 />//開啟配置項
              
          <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,此方法不能有返回值和參數,該方法只一個標識
                       * Pointcut的內容是一個表達式,描述那些對象的那些方法(訂閱Joinpoint)
                       * 定義
                       
          */

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

                      @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()")//環繞通知
                      public Object doBasicProfiling(ProceedingJoinPiont pjp) throws Throwable{
                        
          if(){//判斷是否有權限
                          System.out.println("進入方法");
                              Object result
          =pjp.proceed();//如果不調用這個方法,后面的業務bean及切面將不會執行
                            }

                          
          return result;
                      }

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

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

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

          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();//得到參數集合
                        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  調用
          BeanFactory factory=new ClassPathXmlApplicationContext("applicationContext.xml");
                  UserManager userManager
          =(UserManager)factory.getBean("userManager");
                  userManager.addUser(
          "張三""123456");
          ---------------------------------------------------------------------------------------------------
          JDK動態代理和CGLIB
          手動編寫代碼:
          public class CGlibProxy implements MethodInterceptor{
              
          private Object targetObject;//代理目標對象
              public Object createProxyIntance(Object targetObject){
                  
          this.targetObject=targetObject;
                  Enhancer enhancer
          =new Enhancer();//該類用于生成代理對象
                  
          //非final,繼承目標類,并對非final方法進行復蓋
                  enhancer.setSuperclass(this.targetObject.getClass());//設置父類
                  enhancer.setCallback(this);//設置回調用對象為本身
                  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 如果目標對象實現了接口,默認情況下會采用JDK的動態代理實現AOP
          2 如果目標對象實現了接口,可以強制使用CGLIB實現AOP
          3 如查目標對象沒有實現接口,必須采用CGLIB庫,spring會自動在JDK動態代理和CGLIB之間轉換

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

          -------------------------------------------------------------------------------------------------------
          spring1.2 AOP實現方法
          1 advice類
          public class LogAdvice implements MethodBeforeAdvice {
              
          public void before(Method m, Object[] arg1, Object arg2)
                      
          throws Throwable {    
                  System.out.println(
          new Date()+"時間,調用了,"+m.getName()+"方法,參數為"+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
          * 原始
          <!-- 定義實現類 -->
          <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>
          -->
          * 結合
          <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 調用
          ApplicationContext  ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
          HelloBiz hellobiz
          =(HelloBiz)ctx.getBean("hellobiz");
          hellobiz.say(
          "劉德華");
          posted on 2009-11-30 08:36 junly 閱讀(351) 評論(0)  編輯  收藏 所屬分類: spring

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


          網站導航:
           
          主站蜘蛛池模板: 阿拉尔市| 龙游县| 海口市| 和政县| 绥江县| 兴化市| 台中市| 神农架林区| 阿拉善盟| 惠东县| 大荔县| 镇沅| 岳普湖县| 灵寿县| 平泉县| 河西区| 靖远县| 临西县| 拉萨市| 石楼县| 同德县| 博爱县| 通州区| 南丹县| 盖州市| 定州市| 巴中市| 阿拉善盟| 思茅市| 义乌市| 罗江县| 呼伦贝尔市| 定襄县| 丹江口市| 深水埗区| 克什克腾旗| 宜黄县| 梁山县| 横山县| 武山县| 尖扎县|