溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java?Spring?AOP該怎么理解

發(fā)布時間:2022-01-05 11:56:35 來源:億速云 閱讀:182 作者:柒染 欄目:開發(fā)技術(shù)

這篇文章給大家介紹Java Spring AOP該怎么理解,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

    前言

    面向切面編程,利用 AOP 可以對業(yè)務(wù)邏輯的各個部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發(fā)的效率。
    即不改變源代碼而添加新功能,可插拔的.

    提示:以下是本篇文章正文內(nèi)容,下面案例可供參考

    一.AOP底層原理

    1.AOP底層使用動態(tài)代理

    有接口:jdk動態(tài)代理,即創(chuàng)建接口實(shí)現(xiàn)類代理對象

    無接口:CGLIB動態(tài)代理,即創(chuàng)建子類代理對象

    jdk動態(tài)代理的實(shí)現(xiàn)

    Java?Spring?AOP該怎么理解

    創(chuàng)建接口

    package com.vector.spring5;
    
    public interface UserDao {
        public int add(int a,int b);
        public String update(String id);
    }

    接口實(shí)現(xiàn)類

    接口實(shí)現(xiàn)類的方法,屬于源代碼,用aop思想增添新功能時這里不能動!

    package com.vector.spring5;
    
    public class UserDaoImpl implements UserDao{
    
        @Override
        public int add(int a, int b) {
            return a+b;
        }
    
        @Override
        public String update(String id) {
            return id;
        }
    }

    使用JDK動態(tài)代理對象,增添新功能

    package com.vector.spring5;
    
    import java.lang.reflect.Array;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.Arrays;
    
    public class JDKProxy {
        public static void main(String[] args) {
            //創(chuàng)建接口實(shí)現(xiàn)類代理對象
            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{
        //有參構(gòu)造傳遞增強(qiáng)對象
        private Object obj;
        public UserDaoProxy(){};
        public UserDaoProxy(Object obj){
            this.obj=obj;
        }
        //增強(qiáng)的邏輯
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //方法之前
            System.out.println("方法之前執(zhí)行: "+method.getName()+":傳遞的參數(shù): "+ Arrays.toString(args));
            //被增強(qiáng)的方法執(zhí)行
            //可以根據(jù)method.getName()判斷選擇增強(qiáng)
            Object res = method.invoke(obj,args);
            //方法之后
            System.out.println("方法之后執(zhí)行: "+obj);
            return res;
        }
    }

    Java?Spring?AOP該怎么理解

    jdk代理圖像解析

    Java?Spring?AOP該怎么理解

    Java?Spring?AOP該怎么理解

    二.AOP術(shù)語

    1.連接點(diǎn)

    類里可以被增強(qiáng)的方法,稱為連接點(diǎn).

    2.切入點(diǎn)

    類中實(shí)際被增強(qiáng)的方法,成為切入點(diǎn).

    3.通知(增強(qiáng))

    (1)實(shí)際被增強(qiáng)的方法中的邏輯部分稱為通知(增強(qiáng)).

    (2)通知包含:前置通知,后置通知,環(huán)繞通知,異常通知,最終通知

    4.切面

    把增強(qiáng)應(yīng)用到切入點(diǎn)的過程稱為切面

    三.AOP 操作(準(zhǔn)備工作)

    Spring 框架一般都是基于 AspectJ 實(shí)現(xiàn) AOP 操作

    (1)AspectJ 不是 Spring 組成部分,獨(dú)立 AOP 框架,一般把 AspectJ 和 Spirng 框架一起使用,進(jìn)行 AOP 操作

    maven準(zhǔn)備

    <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.9.8.RC1</version>
            </dependency>

    方式一:使用Spring的接口實(shí)現(xiàn)增添功能

    實(shí)現(xiàn)組合crud和日志功能結(jié)合

    applicationContext.xml

        <context:component-scan base-package="com.vector"/>
        <aop:config>
    <!--        切入點(diǎn): expression:表達(dá)式 execution(要執(zhí)行的位置!* * * * *)-->
            <aop:pointcut id="pointcut" expression="execution(* com.vector.service.UserServiceImpl.*(..))"/>
    
    <!--        執(zhí)行環(huán)繞增加!-->
            <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
            <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
        </aop:config>

    log.java

    package com.vector.log;
    
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    
    @Component("log")
    public class Log implements MethodBeforeAdvice {
        //method: 要執(zhí)行的目標(biāo)對象的方法
        //args: 參數(shù)
        //target: 目標(biāo)對象
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println(target.getClass().getName()+"的"+method.getName()+"被執(zhí)行了");
    
        }
    }

    userService.java

    package com.vector.service;
    
    
    public interface UserService {
        public void add();
        public void delete();
        public void update();
        public void query();
    }

    userServiceImpl.java

    package com.vector.service;
    
    import org.springframework.stereotype.Service;
    
    @Service("userService")
    public class UserServiceImpl implements UserService{
        @Override
        public void add() {
            System.out.println("增加了一個用戶");
        }
    }

    MyTest.java

    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            //動態(tài)代理的是接口
            UserService userService = (UserService) context.getBean("userService");
            userService.add();
        }
    }

    Java?Spring?AOP該怎么理解

    方式二:自定義類

    DiyPoint.java

    package com.vector.diy;
    
    import org.springframework.stereotype.Component;
    
    @Component("diyPointCut")
    public class DiyPointCut {
        public void before(){
            System.out.println("===方法執(zhí)行前===");
        }
        public void after(){
            System.out.println("===方法執(zhí)行后===");
        }
    }

    UserServiceImpl.java

    package com.vector.service;
    
    import org.springframework.stereotype.Service;
    
    @Service("userService")
    public class UserServiceImpl implements UserService{
        @Override
        public void add() {
            System.out.println("增加了一個用戶");
        }
    }

    applicationContext.xml

        <aop:config>
    <!--        自定義切面,ref要引用的類-->
            <aop:aspect ref="diyPointCut">
    <!--            切入點(diǎn)-->
                <aop:pointcut id="pointcut" expression="execution(* com.vector.service.UserServiceImpl.*(..))"/>
    <!--            通知-->
                <aop:before method="before" pointcut-ref="pointcut"/>
                <aop:after method="after" pointcut-ref="pointcut"/>
            </aop:aspect>
        </aop:config>

    MyTest.java

    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            //動態(tài)代理的是接口
            UserService userService = (UserService) context.getBean("userService");
            userService.add();
        }
    }

    Java?Spring?AOP該怎么理解

    方式三:全注解配置實(shí)現(xiàn)

    UserServiceImpl.java

    package com.vector.service;
    
    import org.springframework.stereotype.Service;
    
    @Service("userService")
    public class UserServiceImpl implements UserService{
        @Override
        public void add() {
            System.out.println("增加了一個用戶");
        }
    }

    AnnotationPointCut.java

    package com.vector;
    
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    import org.springframework.stereotype.Component;
    
    //標(biāo)注這個類是一個切面
    @Aspect
    @Component("annotationPointCut")
    //開啟aop注解驅(qū)動
    @EnableAspectJAutoProxy
    public class AnnotationPointCut {
        @Before("execution(* com.vector.service.UserServiceImpl.*(..))")
        public void before(){
            System.out.println("===方法執(zhí)行前===");
        }
        @After("execution(* com.vector.service.UserServiceImpl.*(..))")
        public void after(){
            System.out.println("===方法執(zhí)行后===");
        }
    }

    MyTest.java

    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            //動態(tài)代理的是接口
            UserService userService = (UserService) context.getBean("userService");
            userService.add();
        }
    }

    Java?Spring?AOP該怎么理解

    關(guān)于Java Spring AOP該怎么理解就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI