亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

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

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

SpringBoot中怎么利用AOP和攔截器實現自定義注解

發布時間:2022-07-04 10:18:04 來源:億速云 閱讀:184 作者:iii 欄目:開發技術

本篇內容主要講解“SpringBoot中怎么利用AOP和攔截器實現自定義注解”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“SpringBoot中怎么利用AOP和攔截器實現自定義注解”吧!

    Spring實現自定義注解

    通過攔截器+AOP實現自定義注解的實現,在這里攔截器充當在指定注解處要執行的方法,aop負責將攔截器的方法和要注解生效的地方做一個織入(通過動態注解生成代理類實現)。

    1.引入相關依賴

    spring-boot-starter:spring的一些核心基礎依賴

    spring-boot-starter-aop:spring實現Aop的一些相關依賴

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>

    2.相關類

    1.自定義注解類

    @Target({ElementType.TYPE})  //說明了Annotation所修飾的對象范圍,這里,的作用范圍是類、接口(包括注解類型) 或enum
    @Retention(RetentionPolicy.RUNTIME)  //自定義注解的有效期,Runtime:注解不僅被保存到class文件中,jvm加載class文件之后,仍然存在
    @Documented //標注生成javadoc的時候是否會被記錄
    public @interface EasyExceptionResult {
    }

    2.攔截器類

    /**
     * MethodInterceptor是AOP項目中的攔截器(注:不是動態代理攔截器),
     * 區別與HandlerInterceptor攔截目標時請求,它攔截的目標是方法。
     */
    public class EasyExceptionIntercepter implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            AnnotatedElement element=invocation.getThis().getClass();
            EasyExceptionResult easyExceptionResult=element.getAnnotation(EasyExceptionResult.class);
            if (easyExceptionResult == null) {
                return invocation.proceed();
            }
            try {
                return invocation.proceed();
            } catch (Exception rpcException) {
                //不同環境下的一個異常處理
                System.out.println("發生異常了");
                return null;
            }
        }
    }

    3.切點切面類

    MethodInterceptor的實現類能作為切面的執行方式是應為Interceptor的父類是Advice。

    @Configuration
    public class EasyExceptionAdvisor {
     
        /**
         * 放在最后執行
         * 等待ump/日志等記錄結束
         *
         * @return {@link DefaultPointcutAdvisor}對象
         */
        @Bean
        @Order(Integer.MIN_VALUE)
        public DefaultPointcutAdvisor easyExceptionResultAdvisor() {
            DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
            //針對EasyExceptionResult注解創建切點
            AnnotationMatchingPointcut annotationMatchingPointcut = new AnnotationMatchingPointcut(EasyExceptionResult.class, true);
            EasyExceptionIntercepter interceptor = new EasyExceptionIntercepter();
            advisor.setPointcut(annotationMatchingPointcut);
            //在切點執行interceptor中的invoke方法
            advisor.setAdvice(interceptor);
            return advisor;
        }
     
    }

    4.自定義注解的使用

    @Service
    @EasyExceptionResult  //自定義異常捕獲注解
    public class EasyServiceImpl {
     
        public void testEasyResult(){
            throw new NullPointerException("測試自定義注解");
        }
     
    }

    5.效果

    @SpringBootApplication
    public class JdStudyApplication {
     
        public static void main(String[] args) {
            ConfigurableApplicationContext context=SpringApplication.run(JdStudyApplication.class, args);
            EasyServiceImpl easyService=context.getBean(EasyServiceImpl.class);
            easyService.testEasyResult();
        }
     
    }

    SpringBoot中怎么利用AOP和攔截器實現自定義注解

    至此就實現了通過spring實現自定義注解。

    Java實現自定義注解

    雖然通過Spring實現了自定義注解但是還有辦法讓我們不通過Spring也能實現自定義注解,畢竟注解是早于Spring的。

    JDK中有一些元注解,主要有@Target,@Retention,@Document,@Inherited用來修飾注解,如下為一個自定義注解。

    @Target({ElementType.TYPE})  //說明了Annotation所修飾的對象范圍,這里,的作用范圍是類、接口(包括注解類型) 或enum
    @Retention(RetentionPolicy.RUNTIME)  //自定義注解的有效期,Runtime:注解不僅被保存到class文件中,jvm加載class文件之后,仍然存在
    @Documented //標注生成javadoc的時候是否會被記錄
    public @interface EasyExceptionResult {
    }

    @Target

    表明該注解可以應用的java元素類型

    Target類型描述
    ElementType.TYPE應用于類、接口(包括注解類型)、枚舉
    ElementType.FIELD應用于屬性(包括枚舉中的常量)
    ElementType.METHOD應用于方法
    ElementType.PARAMETER應用于方法的形參
    ElementType.CONSTRUCTOR應用于構造函數
    ElementType.LOCAL_VARIABLE應用于局部變量
    ElementType.ANNOTATION_TYPE應用于注解類型
    ElementType.PACKAGE應用于包
    ElementType.TYPE_PARAMETER1.8版本新增,應用于類型變量)
    ElementType.TYPE_USE1.8版本新增,應用于任何使用類型的語句中(例如聲明語句、泛型和強制轉換語句中的類型)

    @Retention

    表明該注解的生命周期

    生命周期類型描述
    RetentionPolicy.SOURCE編譯時被丟棄,不包含在類文件中
    RetentionPolicy.CLASSJVM加載時被丟棄,包含在類文件中,默認值
    RetentionPolicy.RUNTIME由JVM 加載,包含在類文件中,在運行時可以被獲取到

    @Document

    表明該注解標記的元素可以被Javadoc 或類似的工具文檔化

    @Inherited

    表明使用了@Inherited注解的注解,所標記的類的子類也會擁有這個注解

    通過Cglib實現

    在我們定義好注解之后就需要考慮如何將注解和類綁定到一起,在運行期間達到我們想要的效果,這里就可以引入動態代理的機制,將注解想要做的操作在方法執行前,類編譯時就進行一個織入的操作如下。  

    public static void main(String[] args) {
            Class easyServiceImplClass=EasyServiceImpl.class;
            //判斷該對象是否有我們自定義的@EasyExceptionResult注解
            if(easyServiceImplClass.isAnnotationPresent(EasyExceptionResult.class)){
                final EasyServiceImpl easyService=new EasyServiceImpl();
                //cglib的字節碼加強器
                Enhancer enhancer=new Enhancer();
                將目標對象所在的類作為Enhaner類的父類
                enhancer.setSuperclass(EasyServiceImpl.class);
                通過實現MethodInterceptor實現方法回調,MethodInterceptor繼承了Callback
                enhancer.setCallback(new MethodInterceptor() {
                    @Override
                    public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        try{
                            method.invoke(easyService, args);
                            System.out.println("事務結束...");
                        }catch (Exception e){
                            System.out.println("發生異常了");
                        }
                        return proxy;
                    }
                });
     
                Object obj= enhancer.create();;
                EasyServiceImpl easyServiceProxy=(EasyServiceImpl)obj;
                easyServiceProxy.testEasyResult();
            }
     
        }

    運行效果:

    SpringBoot中怎么利用AOP和攔截器實現自定義注解

    通過JDk動態代理實現

    public class EasyServiceImplProxy implements InvocationHandler {
     
        private EasyServiceImpl target;
     
        public void setTarget(EasyServiceImpl target)
        {
            this.target = target;
        }
     
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 這里可以做增強
            System.out.println("已經是代理類啦");
            try{
                return  method.invoke(proxy, args);
            }catch (Exception e){
                System.out.println("發生異常了");
                return null;
            }
        }
     
     
        /**
         * 生成代理類
         * @return 代理類
         */
        public Object CreatProxyedObj()
        {
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
    }

    Cglib和JDK動態代理的區別

    java動態代理是利用反射機制生成一個實現代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理。

    而cglib動態代理是利用asm開源包,對代理對象類的class文件加載進來,通過修改其字節碼生成子類來處理。

    1、如果目標對象實現了接口,默認情況下會采用JDK的動態代理實現AOP 

    2、如果目標對象實現了接口,可以強制使用CGLIB實現AOP 

    3、如果目標對象沒有實現了接口,必須采用CGLIB庫,spring會自動在JDK動態代理和CGLIB之間轉換

    如何強制使用CGLIB實現AOP?

    (1)添加CGLIB庫,SPRING_HOME/cglib/*.jar

    (2)在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

    JDK動態代理和CGLIB字節碼生成的區別?

    (1)JDK動態代理只能對實現了接口的類生成代理,而不能針對類

    (2)CGLIB是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法

    因為是繼承,所以該類或方法最好不要聲明成final 

    到此,相信大家對“SpringBoot中怎么利用AOP和攔截器實現自定義注解”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    绍兴县| 云南省| 乌拉特中旗| 盘山县| 嘉鱼县| 通榆县| 密山市| 武穴市| 抚松县| 台安县| 凤阳县| 安平县| 华亭县| 新乡市| 措勤县| 龙江县| 永新县| 元氏县| 常德市| 探索| 福鼎市| 扬中市| 卓尼县| 昌平区| 西乡县| 苏州市| 会理县| 崇仁县| 碌曲县| 武冈市| 喀什市| 余庆县| 黑河市| 鄂托克旗| 民丰县| 玉溪市| 济宁市| 缙云县| 彰武县| 山东| 双城市|