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).
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>
1 kelas anotasi tersuai
@Target({ElementType.TYPE}) //说明了Annotation所修饰的对象范围,这里,的作用范围是类、接口(包括注解类型) 或enum @Retention(RetentionPolicy.RUNTIME) //自定义注解的有效期,Runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在 @Documented //标注生成javadoc的时候是否会被记录 public @interface EasyExceptionResult { }
2
3. Kelas aspek PointcutKelas 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; } } }
@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;
}
}
@Service
@EasyExceptionResult //自定义异常捕获注解
public class EasyServiceImpl {
public void testEasyResult(){
throw new NullPointerException("测试自定义注解");
}
}
Kini anda telah melaksanakan anotasi tersuai melalui musim bunga.
Java melaksanakan anotasi tersuai
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(); } }
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_PARAMETER | 1.8版本新增,应用于类型变量) |
ElementType.TYPE_USE | 1.8版本新增,应用于任何使用类型的语句中(例如声明语句、泛型和强制转换语句中的类型) |
Menunjukkan kitaran hayat anotasi
生命周期类型 | 描述 |
---|---|
RetentionPolicy.SOURCE | 编译时被丢弃,不包含在类文件中 |
RetentionPolicy.CLASS | JVM加载时被丢弃,包含在类文件中,默认值 |
RetentionPolicy.RUNTIME | 由JVM 加载,包含在类文件中,在运行时可以被获取到 |
Menunjukkan bahawa elemen yang ditandakan oleh anotasi boleh didokumenkan oleh Javadoc atau alatan serupa
@Inheritedmenunjukkan bahawa anotasi @Inherited digunakan dan subkelas kelas yang ditandakan juga akan mempunyai anotasi ini
Dilaksanakan oleh Cglib
@Target({ElementType.TYPE}) //说明了Annotation所修饰的对象范围,这里,的作用范围是类、接口(包括注解类型) 或enum @Retention(RetentionPolicy.RUNTIME) //自定义注解的有效期,Runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在 @Documented //标注生成javadoc的时候是否会被记录 public @interface EasyExceptionResult { }
Kesan operasi:
Dicapai 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(); } }
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
(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!