Rumah > Java > javaTutorial > Cara menggunakan AOP dan pemintas untuk melaksanakan anotasi tersuai dalam SpringBoot

Cara menggunakan AOP dan pemintas untuk melaksanakan anotasi tersuai dalam SpringBoot

PHPz
Lepaskan: 2023-05-29 19:58:00
ke hadapan
1016 orang telah melayarinya

    Spring melaksanakan anotasi tersuai

    Melaksanakan anotasi tersuai melalui pemintas + AOP, di mana pemintas bertindak sebagai fungsi yang akan dilaksanakan pada Kaedah anotasi yang ditentukan, AOP bertanggungjawab untuk menganyam kaedah pemintas dan tempat di mana anotasi berkuat kuasa (menjana pelaksanaan kelas proksi melalui anotasi dinamik).

    1. Memperkenalkan kebergantungan berkaitan

    spring-boot-starter: beberapa kebergantungan asas teras spring

    spring-boot-starter-aop: beberapa kebergantungan spring-boot-starter yang berkaitan untuk dilaksanakan 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>
    Salin selepas log masuk

    2. Kelas berkaitan

    1 kelas anotasi tersuai

    @Target({ElementType.TYPE})  //说明了Annotation所修饰的对象范围,这里,的作用范围是类、接口(包括注解类型) 或enum
    @Retention(RetentionPolicy.RUNTIME)  //自定义注解的有效期,Runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在
    @Documented //标注生成javadoc的时候是否会被记录
    public @interface EasyExceptionResult {
    }
    Salin selepas log masuk
    Salin selepas log masuk

    2

    3. Kelas aspek Pointcut

    Kelas pelaksanaan MethodInterceptor boleh digunakan sebagai kaedah pelaksanaan aspek kerana kelas induk Pemindas ialah Nasihat.

    /**
     * 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;
            }
        }
    }
    Salin selepas log masuk

    4. Penggunaan anotasi tersuai

    @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;
        }
     
    }
    Salin selepas log masuk

    5. Kesan

    @Service
    @EasyExceptionResult  //自定义异常捕获注解
    public class EasyServiceImpl {
     
        public void testEasyResult(){
            throw new NullPointerException("测试自定义注解");
        }
     
    }
    Salin selepas log masuk

    Cara menggunakan AOP dan pemintas untuk melaksanakan anotasi tersuai dalam SpringBootKini anda telah melaksanakan anotasi tersuai melalui musim bunga.

    Java melaksanakan anotasi tersuai

    Walaupun anotasi tersuai dilaksanakan melalui Spring, masih ada cara untuk kami melaksanakan anotasi tersuai tanpa menggunakan Spring Lagipun, anotasi lebih awal daripada Spring.

    Terdapat beberapa meta-anotasi dalam JDK, terutamanya @Target, @Retention, @Document dan @Inherited, yang digunakan untuk mengubah suai anotasi berikut ialah anotasi tersuai.

    @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();
        }
     
    }
    Salin selepas log masuk

    @Target

    Menunjukkan jenis elemen java yang mana anotasi ini boleh digunakan

    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

    Menunjukkan kitaran hayat anotasi

    生命周期类型描述
    RetentionPolicy.SOURCE编译时被丢弃,不包含在类文件中
    RetentionPolicy.CLASSJVM加载时被丢弃,包含在类文件中,默认值
    RetentionPolicy.RUNTIME由JVM 加载,包含在类文件中,在运行时可以被获取到
    @Document

    Menunjukkan bahawa elemen yang ditandakan oleh anotasi boleh didokumenkan oleh Javadoc atau alatan serupa

    @Inherited

    menunjukkan bahawa anotasi @Inherited digunakan dan subkelas kelas yang ditandakan juga akan mempunyai anotasi ini

    Dilaksanakan oleh Cglib

    Selepas kami mentakrifkan anotasi, kami perlu mempertimbangkan cara untuk mengikat anotasi dan kelas bersama-sama untuk mencapai kesan yang kami inginkan semasa masa jalanan Di sini kami boleh memperkenalkan mekanisme proksi dinamik dan meletakkan operasi yang dikehendaki oleh anotasi untuk dilakukan dalam kaedah Sebelum pelaksanaan, operasi anyaman dilakukan apabila kelas disusun seperti berikut.

    @Target({ElementType.TYPE})  //说明了Annotation所修饰的对象范围,这里,的作用范围是类、接口(包括注解类型) 或enum
    @Retention(RetentionPolicy.RUNTIME)  //自定义注解的有效期,Runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在
    @Documented //标注生成javadoc的时候是否会被记录
    public @interface EasyExceptionResult {
    }
    Salin selepas log masuk
    Salin selepas log masuk

    Kesan operasi:

    Cara menggunakan AOP dan pemintas untuk melaksanakan anotasi tersuai dalam SpringBootDicapai melalui proksi dinamik JDk

    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();
            }
     
        }
    Salin selepas log masuk

    Perbezaan antara proksi dinamik Cglib dan JDK

    Proksi dinamik Java menggunakan mekanisme pantulan untuk menjana kelas tanpa nama yang melaksanakan antara muka proksi, dan memanggil InvokeHandler untuk memprosesnya sebelum memanggil kaedah tertentu.

    Proksi dinamik cglib menggunakan pakej sumber terbuka asm untuk memuatkan fail kelas kelas objek proksi dan mengubah suai kod baitnya untuk menjana subkelas untuk pemprosesan.

    1 Jika objek sasaran melaksanakan antara muka, proksi dinamik JDK akan digunakan secara lalai untuk melaksanakan AOP

    2. Jika objek sasaran melaksanakan antara muka, anda boleh memaksa penggunaan CGLIB untuk melaksanakan AOP

    3 Jika objek sasaran tidak melaksanakan antara muka, pustaka CGLIB mesti digunakan secara automatik antara proksi dinamik JDK dan CGLIB

    Cara memaksa. penggunaan CGLIB untuk melaksanakan AOP?

    (1) Tambahkan perpustakaan CGLIB, SPRING_HOME/cglib/*.jar

    (2) Tambahkan

    Apakah perbezaan antara proksi dinamik JDK dan penjanaan kod bait CGLIB?

    (1) Proksi dinamik JDK hanya boleh menjana proksi untuk kelas yang melaksanakan antara muka, tetapi bukan untuk kelas

    (2) CGLIB melaksanakan proksi untuk kelas, terutamanya untuk yang ditentukan Kelas menjana subkelas dan mengatasi kaedah

    Oleh kerana ia adalah warisan, sebaiknya jangan mengisytiharkan kelas atau kaedah sebagai muktamad

    Atas ialah kandungan terperinci Cara menggunakan AOP dan pemintas untuk melaksanakan anotasi tersuai dalam SpringBoot. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

    Label berkaitan:
    sumber:yisu.com
    Kenyataan Laman Web ini
    Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
    Tutorial Popular
    Lagi>
    Muat turun terkini
    Lagi>
    kesan web
    Kod sumber laman web
    Bahan laman web
    Templat hujung hadapan