what kind of method can be advised by spring aop or what#39;s a spring aop joinpoint#39;s limitation?(Spring AOP可以建议使用哪种方法,或者Spring AOP连接点的限制是什么?)
问题描述
我正在使用Spring AOP,我发现有3种情况,但我不太清楚: 情形1:没有实现或扩展任何类或接口的单个类 在这种情况下,任何非私有方法都将是连接点 情形2:类实现接口并实现方法 在此缝合中,只有在接口中声明的方法将是连接点 情形3:类扩展超类并覆盖超类的方法 在此缝合中,所有子类的方法都不是连接点。
Spring AOP就是这样设计的吗?
以下是我使用的代码:
JdkProxyInterface.java
package com.example.proxytestdemo;
public interface JdkProxyInterface {
void function(int i);
}
JdkProxy.java
package com.example.proxytestdemo;
import org.springframework.stereotype.Component;
@Component
public class JdkProxy implements JdkProxyInterface {
@Override
@TimeIt
public void function(int i) {
System.out.println("JdkProxy function");
}
@TimeIt
public void function1(int i) {
System.out.println("JdkProxy function");
}
@TimeIt
public void function2(int i) {
System.out.println("JdkProxy function");
}
}
SubJdkProxy.java
package com.example.proxytestdemo;
import org.springframework.stereotype.Component;
@Component
public class SubJdkProxy extends JdkProxy {
@TimeIt
public void functionSubJdkProxy(int i) {
System.out.println("functionSubJdkProxy");
}
}
TimeIt.Java
package com.example.proxytestdemo;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
@Inherited
public @interface TimeIt {
boolean enabled() default true;
}
TimePointCut.java
package com.example.proxytestdemo;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Aspect
@Component
public class TimePointCut {
@Pointcut("execution(* com.example.proxytestdemo..*(..))")
public void calcTime1() {
}
@Around(value = "calcTime1()")
public Object aspectProcess(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("proxy begin....... ");
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
TimeIt annotation = method.getAnnotation(com.example.proxytestdemo.TimeIt.class);
if (annotation == null) {
annotation = pjp.getTarget().getClass().getAnnotation(TimeIt.class);
if (annotation == null) {
for (Class<?> cls : pjp.getClass().getInterfaces()) {
annotation = cls.getAnnotation(TimeIt.class);
if (annotation != null) {
break;
}
}
}
}
if (annotation != null) {
System.out.println(annotation.enabled());
}
Object o = null;
long t1 = 0, t2 = 0;
try {
t1 = System.currentTimeMillis();
o = pjp.proceed();
t2 = System.currentTimeMillis();
} catch (Exception e) {
throw e;
} finally {
System.out.println("proxy end....... ");
System.out.println("time cost: "+ (t2-t1)/1000 + "s");
}
return o;
}
}
我发现不能建议使用JdkProxy.unction1()和JdkProxy.unction2()和SubJdkProxy.unctionSubJdkProxy()。
对不起,由于IDEA的提示,我犯了一个错误。IDEA's hint
推荐答案
您的应用程序应该可以工作。听着,我尝试了各种组合,它们都很管用:
驱动程序应用程序:
package com.example.proxytestdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
try (ConfigurableApplicationContext context = SpringApplication.run(Application.class, args)) {
doStuff(context);
}
}
private static void doStuff(ConfigurableApplicationContext context) {
JdkProxy jdkProxy = (JdkProxy) context.getBean("jdkProxy");
jdkProxy.function(11);
jdkProxy.function1(22);
jdkProxy.function2(33);
System.out.println("----------");
JdkProxyInterface jdkProxyInterface = jdkProxy ;
jdkProxyInterface.function(11);
System.out.println("==========");
SubJdkProxy subJdkProxy = (SubJdkProxy) context.getBean("subJdkProxy");
subJdkProxy.function(11);
subJdkProxy.function1(22);
subJdkProxy.function2(33);
subJdkProxy.functionSubJdkProxy(44);
System.out.println("----------");
jdkProxyInterface = subJdkProxy;
jdkProxyInterface.function(11);
}
}
控制台日志:
execution(void com.example.proxytestdemo.JdkProxy.function(int))
JdkProxy function
execution(void com.example.proxytestdemo.JdkProxy.function1(int))
JdkProxy function
execution(void com.example.proxytestdemo.JdkProxy.function2(int))
JdkProxy function
----------
execution(void com.example.proxytestdemo.JdkProxy.function(int))
JdkProxy function
==========
execution(void com.example.proxytestdemo.JdkProxy.function(int))
JdkProxy function
execution(void com.example.proxytestdemo.JdkProxy.function1(int))
JdkProxy function
execution(void com.example.proxytestdemo.JdkProxy.function2(int))
JdkProxy function
execution(void com.example.proxytestdemo.SubJdkProxy.functionSubJdkProxy(int))
functionSubJdkProxy
----------
execution(void com.example.proxytestdemo.JdkProxy.function(int))
JdkProxy function
顺便说一句,为了专注于基础工作,我将方面的建议方法简化为:
@Around(value = "calcTime1()")
public Object aspectProcess(ProceedingJoinPoint pjp) throws Throwable {
System.out.println(pjp);
return pjp.proceed();
}
更新:
Spring Boot默认为CGLIB代理模式,当前无法轻松重新配置为使用JDK代理,因为相应的注释被忽略或被取代,请参见issue #12194。但我找到了一种方法,见my comment on Spring Boot #27375。您需要将此内容放入application.properties
:
spring.aop.proxy-target-class=false
但是,普通Spring默认使用JDK代理模式。您必须在类路径上设置一个没有任何Boot依赖项的经典Spring项目。但是,当然,只有接口定义的方法被代理,您不能使用在接口外部定义的方法。您也可以将Spring切换到CGLIB模式,但不能将其引导到JDK模式。
因为这是一个常见的问题,而且我喜欢有一个游乐场项目来回答相关的问题,为了您的方便,我发布了this GitHub project。您可以随意查看它、克隆它并玩弄它。
更新2022-02-26:Here您可以学习如何使用Spring自己的帮助器类确定Spring AOP代理类型(JDK与CGLIB代理)。
这篇关于Spring AOP可以建议使用哪种方法,或者Spring AOP连接点的限制是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:Spring AOP可以建议使用哪种方法,或者Spring AOP连接
基础教程推荐
- “未找到匹配项"使用 matcher 的 group 方法时 2022-01-01
- Java:带有char数组的println给出乱码 2022-01-01
- 设置 bean 时出现 Nullpointerexception 2022-01-01
- 如何使用 Java 创建 X509 证书? 2022-01-01
- 降序排序:Java Map 2022-01-01
- FirebaseListAdapter 不推送聊天应用程序的单个项目 - Firebase-Ui 3.1 2022-01-01
- 无法使用修饰符“public final"访问 java.util.Ha 2022-01-01
- 在 Libgdx 中处理屏幕的正确方法 2022-01-01
- 减少 JVM 暂停时间 >1 秒使用 UseConcMarkSweepGC 2022-01-01
- Java Keytool 导入证书后出错,"keytool error: java.io.FileNotFoundException &拒绝访问" 2022-01-01