国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

Spring框架學(xué)習之AOP詳解

發(fā)布時(shí)間:2021-07-17 21:51 來(lái)源:腳本之家 閱讀:0 作者:不善言談?wù)?/span> 欄目: 編程語(yǔ)言 歡迎投稿:712375056

目錄

    一、概念

    1.面向切面編程(方面),利用 AOP 可以對業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時(shí)提高了開(kāi)發(fā)的效率。

    2.通俗描述:不通過(guò)修改源代碼方式,在主干功能里面添加新功能

    二、底層原理:動(dòng)態(tài)代理

    有兩種情況動(dòng)態(tài)代理

    2.1 有接口, JDK 動(dòng)態(tài)代理

    1.被代理的對象

    public class UserDaoImpl implements UserDao {
    
        @Override
        public int add(int a, int b) {
            System.out.println("add執行");
            return a + b;
        }
    
        @Override
        public String update(String id) {
            System.out.println("update執行");
            return id;
        }
    
    }
    

    2.代理

    package cn.zj.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.Arrays;
    
    import cn.zj.dao.UserDao;
    import cn.zj.dao.impl.UserDaoImpl;
    
    public class JDKProxy {
    
        public static void main(String[] args) {
            // 創(chuàng  )建接口實(shí)現類(lèi)代理對象
            Class[] interfaces = { UserDao.class };
            UserDaoImpl userDao = new UserDaoImpl();
            UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces,
                    new UserDaoProxy(userDao));
            
            int result = dao.add(1, 2);
            System. out .println( "result:"+result);
        }
    }
    
    //創(chuàng  )建代理對象代碼
    class UserDaoProxy implements InvocationHandler {
    
        private Object target;// 目標類(lèi)
    
        public UserDaoProxy(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 方法執行之前
            System.out.println("方法執行之前.." + method.getName() + ";傳遞的參數:" + Arrays.toString(args));
            // 增強方法
            Object res = method.invoke(target, args);
            // 方法執行之后
            System.out.println("方法執行之后.." + target);
            return res;
        }
    
    }
    

    3.打印

    方法執行之前..add;傳遞的參數:[1, 2]
    add執行
    方法執行之后..cn.zj.dao.impl.UserDaoImpl@6c629d6e
    result:3

    2.2 無(wú)接口, CGLIB 動(dòng)態(tài)代理

    1.被代理的對象

    public class Cat {
    
        public void eat() {
            System.out.println("貓吃魚(yú)");
        }
    }

    2.代理

    public class CglibProxy {
    
        public static void main(String[] args) {
            Cat c = new CglibProxy().createProxyObject(Cat.class);
            c.eat();
        }
    
        // JDK代理是對對象做代理,cglib代理是對類(lèi)做代理
        public Cat createProxyObject(Class clazz) {
            // 1.創(chuàng  )建內存中的動(dòng)態(tài)類(lèi) Enhance
            // 內存中造出一個(gè)沒(méi)有名稱(chēng)的動(dòng)態(tài)類(lèi)
            Enhancer enhancer = new Enhancer();
            // 2.現在的類(lèi)最終完成原始類(lèi)的功能,同時(shí)對其進(jìn)行功能的增強,必須先具有原始類(lèi)對應的功能————繼承
            enhancer.setSuperclass(clazz);
            // 3.進(jìn)行功能的增強
            // 設置了方法的調用攔截
            // 設置具體的回調操作
            Callback callback = new MethodInterceptor() {
                // proxy:代理對象
                // method:被攔截的方法對象
                // args:調用參數
                // methodProxy:
                public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
                        throws Throwable {
                    // 做增強
                    System.out.println("執行前");
                    // Object obj=method.invoke(proxy, args);//這種執行是代理類(lèi)的方法,而不是目標類(lèi)的,會(huì )造成內存溢出
                    // 以下的兩種都是執行目標類(lèi)的方法
                    // Object obj = methodProxy.invokeSuper(proxy, args);//執行目標類(lèi)的方法
                    // Object obj=method.invoke(proxy, args);
                    Object res = methodProxy.invokeSuper(proxy, args);
                    System.out.println("執行后");
                    return res;
                }
            };
            enhancer.setCallback(callback);
            // 4.創(chuàng  )建內存中的全新的類(lèi)的對象
            Object proxyObj = enhancer.create();
            return (Cat) proxyObj;
        }
    
    }
    

    三、術(shù)語(yǔ)

    1.連接點(diǎn)(Joinpoint)

    類(lèi)中的任意方法的運行時(shí)表示,可以簡(jiǎn)單理解為類(lèi)中的方法,也就是可以被增強的方法

    2.切入點(diǎn)(Pointcut)

    具有共性功能的方法的運行時(shí)表示,可以簡(jiǎn)單理解為具有共性功能的方法,也就是實(shí)際被增強的方法

    注意:切入點(diǎn)對應的是被挖去了共性功能后的方法執行時(shí)匹配斷言(格式)

    3.通知/增強(Advice)

    共性功能模塊化,可以簡(jiǎn)單理解為將共性功能抽取出來(lái)制作成獨立的方法,實(shí)際增強的邏輯部分

    類(lèi)型:前置,后置,異常,最終,環(huán)繞

    4.切面(Aspect)

    切入點(diǎn)與通知的對應關(guān)系,可以簡(jiǎn)單理解為被抽取的共性功能與共性功能被抽取位置對應的方法之間的關(guān)系,把通知應用到切入點(diǎn)的過(guò)程

    5.目標對象(Target Object)

    包含切入點(diǎn)的運行時(shí)對象,開(kāi)發(fā)階段制作的是目標對象對應的類(lèi)

    6.AOP代理(AOP Proxy)

    使用AOP的代理機制創(chuàng )建目標對象運行時(shí)代理對象,完成原始的功能

    注意:原始目標對象已經(jīng)被挖去了共性功能,此時(shí)使用目標對象執行任務(wù)無(wú)法完成原始任務(wù),使用AOP代理機制,創(chuàng )建一個(gè)代理對象來(lái)完成原始目標對象的功能

    7.織入(Weaving)

    是一個(gè)將通知功能加入原始字節碼的動(dòng)態(tài)過(guò)程,將增強添加對目標類(lèi)具體連接點(diǎn)上的過(guò)程

    Spring使用的是運行時(shí)織入機制

    8.引入(Introduction)

    一種特殊的機制,可以為一個(gè)類(lèi)的字節碼動(dòng)態(tài)的加入變量或方法

    四、操作

    4.1 Spring 框架一般都是基于 AspectJ 實(shí)現 AOP

    AspectJ 不是 Spring 組成部分,獨立 AOP 框架,一般把 AspectJ 和 Spirng 框架一起使

    用,進(jìn)行 AOP 操作

    4.2 實(shí)踐

     1.jar包引入

    <dependencies>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>5.3.6</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>5.3.6</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.3.6</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-expression</artifactId>
                <version>5.3.6</version>
            </dependency>
    
    
    
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aop</artifactId>
                <version>5.3.6</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>1.2</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.2.6</version>
            </dependency>
    
            <!-- @Resource注解需要 -->
            <dependency>
                <groupId>javax.annotation</groupId>
                <artifactId>javax.annotation-api</artifactId>
                <version>1.3.1</version>
            </dependency>
    
    
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
                <version>5.3.6</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/net.sourceforge.cglib/com.springsource.net.sf.cglib -->
            <dependency>
                <groupId>net.sourceforge.cglib</groupId>
                <artifactId>com.springsource.net.sf.cglib</artifactId>
                <version>2.2.0</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.aopalliance/com.springsource.org.aopalliance -->
            <dependency>
                <groupId>org.aopalliance</groupId>
                <artifactId>com.springsource.org.aopalliance</artifactId>
                <version>1.0.0</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.aspectj/com.springsource.org.aspectj.weaver -->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>com.springsource.org.aspectj.weaver</artifactId>
                <version>1.6.8.RELEASE</version>
            </dependency>
    
    
    
        </dependencies>
    

    2.切入點(diǎn)表達式

    作用:知道對哪個(gè)類(lèi)里面的哪個(gè)方法進(jìn)行增強

    語(yǔ)法結構: execution([權限修飾符] [返回類(lèi)型] [類(lèi)全路徑] 方法名稱(chēng) )

    舉例 1:對 com.zj.dao.BookDao 類(lèi)里面的 add 進(jìn)行增強

    execution(* com.zj.dao.BookDao.add(…))

    舉例 2:對 com.zj.dao.BookDao 類(lèi)里面的所有的方法進(jìn)行增強

    execution(* com.zj.dao.BookDao.* (…))

    舉例 3:對 com.zj.dao 包里面所有類(lèi),類(lèi)里面所有方法進(jìn)行增強

    execution(* com.zj.dao.. (…))

    3.xml方式

    1.創(chuàng )建類(lèi)

    package cn.zj.aop.xml;
    
    public class Book {
        public void buy() {
            System.out.println("buy.............");
        }
    }

    2.增強類(lèi)

    package cn.zj.aop.xml;
    
    public class BookProxy {
        public void before() {
            System.out.println("before.........");
        }
    }

    3.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: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.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
        <!--創(chuàng  )建對象-->
        <bean id="book" class="cn.zj.aop.xml.Book"></bean>
        <bean id="bookProxy" class="cn.zj.aop.xml.BookProxy"></bean>
    
        <!--配置aop增強-->
        <aop:config>
            <!--切入點(diǎn)-->
            <aop:pointcut id="p" expression="execution(* cn.zj.aop.xml.Book.buy(..))"/>
            <!--配置切面-->
            <aop:aspect ref="bookProxy">
                <!--增強作用在具體的方法上-->
                <aop:before method="before" pointcut-ref="p"/>
            </aop:aspect>
        </aop:config>
    </beans>
    

    4.注解方式

    1.創(chuàng )建類(lèi)

    public class User {
        public void add() {
            System.out.println("add.......");
        }
    
    }

    2.創(chuàng )建增強類(lèi)

    package cn.zj.aop.an;
    
    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;
    import org.springframework.stereotype.Component;
    
    //增強的類(lèi)
    @Component
    @Aspect  //生成代理對象
    
    public class UserProxy {
    
        //前置通知
        @Before(value = "execution(* cn.zj.aop.an.User.add(..))")
        public void before() {
            System.out.println("before.........");
        }
    
        //后置通知(返回通知)
        @AfterReturning(value = "execution(* cn.zj.aop.an.User.add(..))")
        public void afterReturning() {
            System.out.println("afterReturning.........");
        }
    
        //最終通知
        @After(value = "execution(* cn.zj.aop.an.User.add(..))")
        public void after() {
            System.out.println("after.........");
        }
    
        //異常通知
        @AfterThrowing(value = "execution(* cn.zj.aop.an.User.add(..))")
        public void afterThrowing() {
            System.out.println("afterThrowing.........");
        }
    
        //環(huán)繞通知
        @Around(value = "execution(* cn.zj.aop.an.User.add(..))")
        public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            System.out.println("環(huán)繞之前.........");
    
            //被增強的方法執行
            proceedingJoinPoint.proceed();
    
            System.out.println("環(huán)繞之后.........");
        }
    }
    

    3.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: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.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
        <!-- 開(kāi)啟注解掃描 -->
        <context:component-scan base-package="cn.zj.aop.an"></context:component-scan>
    
        <!-- 開(kāi)啟Aspect生成代理對象-->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    </beans>
    

    4.測試

    ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
            User user = context.getBean("user", User.class);
            user.add();
    

    5.相同點(diǎn)抽取

    //相同切入點(diǎn)抽取
        @Pointcut(value = "execution(* cn.zj.aop.an.User.add(..))")
        public void pointdemo() {
    
        }
    
        //前置通知
        //@Before注解表示作為前置通知
        @Before(value = "pointdemo()")
        public void before() {
            System.out.println("before.........");
        }
    

    6.有多個(gè)增強類(lèi)多同一個(gè)方法進(jìn)行增強,設置增強類(lèi)優(yōu)先級

    在增強類(lèi)上面添加注解 @Order(數字類(lèi)型值),數字類(lèi)型值越小優(yōu)先級越高

    @Component
    @Aspect 
    @Order(1)
    public class PersonProxy {
    
         //后置通知(返回通知)
        @Before(value = "execution(* cn.zj.aop.an.User.add(..))")
        public void afterReturning() {
            System.out.println("Person Before.........");
        }
    }
    //增強的類(lèi)
    @Component
    @Aspect  //生成代理對象
    @Order(2)
    public class UserProxy {
    

    到此這篇關(guān)于Spring框架學(xué)習之AOP詳解的文章就介紹到這了,更多相關(guān)Spring框架AOP內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

    免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。

    国产真实乱子伦精品视频| 亚洲AV网站| 国模无码一区二区三区不卡| 日韩精品极品视频在线观看免费| 98色婷婷在线| 人人妻人人澡人人爽欧美一区九九|