Implementierung benutzerdefinierter Anmerkungen über Interceptor + AOP, wobei der Interceptor als Methode fungiert, die bei der angegebenen Annotation ausgeführt werden soll, und Aop dafür verantwortlich ist, die Methode des Interceptors und die Annotation in Kraft zu setzen Ein Weben vor Ort (Proxy-Klassenimplementierung durch dynamische Annotation generieren).
spring-boot-starter: einige grundlegende Abhängigkeiten von Spring
spring-boot-starter-aop: einige verwandte Abhängigkeiten von Spring, die Aop implementieren
<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. Benutzerdefinierte Annotationsklasse
@Target({ElementType.TYPE}) //说明了Annotation所修饰的对象范围,这里,的作用范围是类、接口(包括注解类型) 或enum @Retention(RetentionPolicy.RUNTIME) //自定义注解的有效期,Runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在 @Documented //标注生成javadoc的时候是否会被记录 public @interface EasyExceptionResult { }
2. Interceptor-Klasse
/** * 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. Die Implementierungsklasse von MethodInterceptor kann als Ausführungsmethode von Aspector verwendet werden, da die übergeordnete Klasse von Interceptor Advice ist. @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("测试自定义注解"); } }
5. Wirkung
@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(); } }
Bisher wurden benutzerdefinierte Anmerkungen bis zum Frühjahr implementiert.
Java implementiert benutzerdefinierte Anmerkungen
Obwohl benutzerdefinierte Anmerkungen über Spring implementiert werden, gibt es für uns immer noch Möglichkeiten, benutzerdefinierte Anmerkungen zu implementieren, ohne Spring zu verwenden. Schließlich gibt es Anmerkungen früher als Spring.
@Target({ElementType.TYPE}) //说明了Annotation所修饰的对象范围,这里,的作用范围是类、接口(包括注解类型) 或enum @Retention(RetentionPolicy.RUNTIME) //自定义注解的有效期,Runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在 @Documented //标注生成javadoc的时候是否会被记录 public @interface EasyExceptionResult { }
Gibt den Java-Elementtyp an, auf den diese Annotation angewendet werden kann
ZieltypElementType.TYPE | |
---|---|
ElementType.FIELD | |
ElementType.METHOD | |
ElementType.PARAMETER | |
ElementType.CONSTRUCTOR | |
ElementType.LOCAL_VARIABLE | |
ElementType.ANNOTATION_TYPE | |
ElementType.PACK AGE | |
ElementType.TYPE_PARAMETER | |
ElementType.TYPE_USE | |
Gibt den Lebenszyklus der Anmerkung an
LebenszyklustypRetentionPolicy.SOURCE | |
---|---|
RetentionPolicy.CLASS | |
RetentionPolicy.RUNTIME | |
gibt an, dass das durch diese Annotation markierte Element von Javadoc oder ähnlichen Tools dokumentiert werden kann
@Inheritedgibt an, dass die Annotation mit der Annotation @Inherited eine ist Unterklasse der markierten Klasse Die Klasse wird auch über diese Annotationimplementiert durch Cglib
Nachdem wir die Annotation definiert haben, müssen wir überlegen, wie wir die Annotation und die Klasse miteinander verbinden, um den gewünschten Effekt zur Laufzeit zu erzielen Wir können den dynamischen Proxy-Mechanismus einführen. Die Annotation möchte die Operation ausführen, bevor die Methode ausgeführt wird, und eine Weboperation wird wie folgt ausgeführt, wenn die Klasse kompiliert wird.
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(); } }
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); } }
1. Wenn das Zielobjekt die Schnittstelle implementiert, wird standardmäßig der dynamische Proxy von JDK verwendet, um AOP zu implementieren.
2 Wenn das Zielobjekt die Schnittstelle implementiert, können Sie die Verwendung von CGLIB erzwingen
3. Wenn das Zielobjekt die Schnittstelle nicht implementiert, muss die CGLIB-Bibliothek verwendet werden. Spring führt automatisch eine Konvertierung zwischen dem dynamischen JDK-Proxy und CGLIB durch.Wie erzwinge ich die Verwendung von CGLIB zur Implementierung von AOP?
(1) Fügen Sie die CGLIB-Bibliothek SPRING_HOME/cglib/*.jar hinzu. (2) Fügen Siein der Spring-Konfiguration hinzu Datei Was ist der Unterschied zwischen dem dynamischen JDK-Proxy und der CGLIB-Bytecode-Generierung?
(1) Der dynamische JDK-Proxy kann nur Proxys für Klassen generieren, die Schnittstellen implementieren, nicht jedoch für Klassen. (2) CGLIB implementiert Proxys für Klassen, hauptsächlich um eine Unterklasse für die angegebene Klasse zu generieren und diese abzudecken MethodeWeil Da es vererbt wird, ist es am besten, die Klasse oder Methode nicht als final zu deklarieren
Das obige ist der detaillierte Inhalt vonSo verwenden Sie AOP und Interceptors, um benutzerdefinierte Anmerkungen in SpringBoot zu implementieren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!