posts - 19, comments - 53, trackbacks - 0, articles - 283
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
          AOP面向切面編程(最突出的是處理權(quán)限控制,在本文中,主要介紹日志處理):

          一、由無組件實現(xiàn)AOP引出Spring AOP

          1. 使用JDK中的Proxy技術(shù)實現(xiàn)AOP功能

          package cn.itcast.aop;

          import java.lang.reflect.InvocationHandler;

          import java.lang.reflect.Method;

          import java.lang.reflect.Proxy;

          import cn.itcast.service.impl.PersonServiceBean;

          public class JDKProxyFactory implements InvocationHandler{

              
          /**

               *要處理的對象(也就是我們要在方法的前后加上業(yè)務(wù)邏輯的對象,如例子中的PersonServiceBean)

               
          */


              
          private Object targetObject;

              

              
          /**

               *動態(tài)生成目標對象的代理

               *@paramtargetObject

               *
          @return

               
          */


              
          public Object createProxyIntance(Object targetObject){

                 
          this.targetObject = targetObject;

                 
          return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(), 

                        
          this.targetObject.getClass().getInterfaces(), this);

              }


              

              
          /**

               *要處理的對象中的每個方法會被此方法送去JVM調(diào)用,也就是說,要處理的對象的方法只能通過此方法調(diào)用

               
          */


              @Override

              
          public Object invoke(Object proxy, Method method, Object[] args)

                     
          throws Throwable //環(huán)繞通知

                 PersonServiceBean bean 
          = (PersonServiceBean) this.targetObject;

                 Object result 
          = null

                 
          if(bean.getUser()!=null){

                     
          //.. advice()-->前置通知

                     System.out.println(method.getName() 
          + "is called¡¤¡¤¡¤¡¤¡¤¡¤");

                     

                     
          try {

                        result 
          = method.invoke(targetObject, args);

                        
          // afteradvice() -->后置通知

                     }
           catch (RuntimeException e) {

                        
          //exceptionadvice()--> 例外通知

                     }
          finally{

                        
          //finallyadvice(); -->最終通知

                     }


                 }


                 
          return result;

              }


          }


           

          2. 使用CGLIB實現(xiàn)AOP功能與AOP概念解釋

          package cn.itcast.aop;

          import java.lang.reflect.Method;

          import cn.itcast.service.impl.PersonServiceBean;

          import net.sf.cglib.proxy.Enhancer;

          import net.sf.cglib.proxy.MethodInterceptor;

          import net.sf.cglib.proxy.MethodProxy;

          /**

           *CGLIB方式實現(xiàn)目標對象的代理

           *CGLIB代理:實現(xiàn)原理類似于JDK動態(tài)代理,只是它在運行期間生成的代理對象是針對目標類擴展的子類。CGLIB是高效的代碼生成包,底層是依靠ASM(開源的java字節(jié)碼編輯類庫)操作字節(jié)碼實現(xiàn)的,性能比JDK強。

           
          */


          publicclass CGlibProxyFactory 
          implements MethodInterceptor{

              
          private Object targetObject;

              
          public Object createProxyIntance(Object targetObject){

                 
          this.targetObject = targetObject;

                 Enhancer enhancer 
          = new Enhancer();

                 enhancer.setSuperclass(
          this.targetObject.getClass());//非final

                 enhancer.setCallback(
          this);

                 
          return enhancer.create();

              }


              @Override

              
          public Object intercept(Object proxy, Method method, Object[] args,

                     MethodProxy methodProxy) 
          throws Throwable {

                 PersonServiceBean bean 
          = (PersonServiceBean) this.targetObject;

                 Object result 
          = null;

                 
          if(bean.getUser()!=null){

                     result 
          = methodProxy.invoke(targetObject, args);

                 }


                 
          return result;

              }


          }


           

             我們省去了業(yè)務(wù)模塊的代碼,因為這是完全獨立于業(yè)務(wù)邏輯的,可以單獨由一個完全不懂業(yè)務(wù)的人管理。測試用例如下:

           

          package junit.test;

          import org.junit.BeforeClass;

          import org.junit.Test;

          import cn.itcast.aop.CGlibProxyFactory;

          import cn.itcast.aop.JDKProxyFactory;

          import cn.itcast.service.PersonService;

          import cn.itcast.service.impl.PersonServiceBean;

          public class AOPTest {

              @BeforeClass

              
          public static void setUpBeforeClass() throws Exception {

              }


              @Test 
          public void proxyTest(){

                 JDKProxyFactory factory 
          = new JDKProxyFactory();

                 PersonService service 
          = (PersonService) factory.createProxyIntance(new PersonServiceBean("xxx"));

                 service.save(
          "888");

              }


              

              @Test 
          public void proxyTest2(){

                 CGlibProxyFactory factory 
          = new CGlibProxyFactory();

                 PersonServiceBean service 
          = (PersonServiceBean) factory.createProxyIntance(new PersonServiceBean("xxx"));

                 service.save(
          "999");

              }


          }

           

          小結(jié):在Spring中,突出的就是業(yè)務(wù)邏輯的處理,AOP則是建立在業(yè)務(wù)邏輯處理的切面上,所以可以通過建立模塊、業(yè)務(wù)層面的切面來對業(yè)務(wù)邏輯方法進行追蹤


          二、Spring提供了兩種切面使用方式:

          1. 基于xml配置方式進行AOP開發(fā)  (鄙人喜歡注解方式,xml配置方式暫不做研究O(∩_∩)O~

          2. 基于注解方式進行AOP開發(fā) 

          定義切面

           

          package cn.itcast.service;

          import org.aspectj.lang.ProceedingJoinPoint;

          import org.aspectj.lang.annotation.After;

          import org.aspectj.lang.annotation.AfterReturning;

          import org.aspectj.lang.annotation.AfterThrowing;

          import org.aspectj.lang.annotation.Around;

          import org.aspectj.lang.annotation.Aspect;

          import org.aspectj.lang.annotation.Before;

          import org.aspectj.lang.annotation.Pointcut;

          /**

           *注解方式定義切面

           
          */


          @Aspect

          publicclass MyInterceptor 
          {

              

              @SuppressWarnings(
          "unused")

              @Pointcut(
          "execution (* cn.itcast.service.impl.PersonServiceBean.*(..))")

              privatevoid anyMethod() 
          {}//聲明一個切入點

              

              @Before(
          "anyMethod() && args(name)")

              publicvoid doAccessCheck(String name) 
          {

                 System.out.println(
          "前置通知:"+ name);

              }


              

              @AfterReturning(pointcut
          ="anyMethod()",returning="result")

              publicvoid doAfterReturning(String result) 
          {

                 System.out.println(
          "后置通知:"+ result);

              }


              

              @After(
          "anyMethod()")

              publicvoid doAfter() 
          {

                 System.out.println(
          "最終通知");

              }


              

              @AfterThrowing(pointcut
          ="anyMethod()",throwing="e")

              publicvoid doAfterThrowing(Exception e) 
          {

                 System.out.println(
          "例外通知:"+ e);

              }


              

              @Around(
          "anyMethod()")

              
          public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {

                 
          //if(){//判斷用戶是否在權(quán)限

                 System.out.println(
          "進入方法");

                 Object result 
          = pjp.proceed();

                 System.out.println(
          "退出方法");

                 
          //}

                 
          return result;

              }
            

          }


          利用Spring AOP必須的組件包:

           

          spring-framework-2.5.6"lib"cglib"cglib-nodep-2.1_3.jar

          spring-framework-2.5.6
          "lib"aspectj"aspectjweaver.jar

          spring-framework-
          2.5.6"lib"aspectj"aspectjrt.jar

          spring-framework-2.5.6
          "lib"j2ee"common-annotations.jar

          spring-framework-
          2.5.6"lib"jakarta-commons"commons-logging.jar

          spring-framework-2.5.6
          "dist"spring.jar

           

          Spring 配置:

           

          <?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:context="http://www.springframework.org/schema/context"

              xmlns:aop
          ="http://www.springframework.org/schema/aop"

              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"
          >

              
          <aop:aspectj-autoproxy />

              
          <bean id="myInterceptor" class="cn.itcast.service.MyInterceptor" />

              
          <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean>

          </beans>

           

          測試用例:

           

          package junit.test;

          import org.junit.BeforeClass;

          import org.junit.Test;

          import org.springframework.context.ApplicationContext;

          import org.springframework.context.support.ClassPathXmlApplicationContext;

          import cn.itcast.service.PersonService;

          publicclass SpringAOPTest 
          {

              @BeforeClass

              publicstaticvoid setUpBeforeClass() 
          throws Exception {

              }


              @Test

              publicvoid interceptorTest() 
          {

                 ApplicationContext cxt 
          = new ClassPathXmlApplicationContext("beans.xml");

                 PersonService personService 
          = (PersonService) cxt.getBean("personService");

                 personService.save(
          "xx");

              }


          }

           


          三、AOP術(shù)語:

          Aspect(切面):指橫切面關(guān)注點的抽象即為切面,它與類相似,只是兩者的關(guān)注點不一樣,類是對物體特征的抽象,而切面是橫切性關(guān)注點的抽象

          Joinpoint(連接點):所謂連接點是指那些被攔截到的點。在Spring中,這些點指的是方法,因為spring只支持方法類型的連接點,實際上joinpoint還可以是field或類構(gòu)造器

          Pointcut(切入點):所謂的切入點是指我們要對那些joinpoint進行攔截的定義

          Advice(通知):所謂的通知是指攔截到joinpoint之后所要做的事情就是通知。通知分為前置通知,后置通知,異常通知,最終通知,環(huán)繞通知

          Target(目標對象):代理的目標對象

          Weave(織入):指將aspects應(yīng)用到target對象并且導致proxy對象創(chuàng)建的過程稱為織入

          Introduction(引入):在不修改類代碼的前提下,introduction可以在運行期為類動態(tài)的添加一些方法或field

          主站蜘蛛池模板: 怀化市| 繁峙县| 五大连池市| 壶关县| 运城市| 仙桃市| 长汀县| 永善县| 广州市| 大邑县| 咸阳市| 灌云县| 高州市| 宿迁市| 资溪县| 新密市| 桐梓县| 南澳县| 六盘水市| 嘉义市| 壶关县| 定南县| 阿城市| 游戏| 宜宾市| 绵阳市| 杨浦区| 赞皇县| 博客| 思南县| 丰镇市| 平乡县| 阳朔县| 清原| 琼中| 上杭县| 威海市| 海兴县| 丹巴县| 大港区| 鄂托克前旗|