maven依赖中引用了consul的spring-cloud-starter-consul-discovery服务发现jar,导致@Controller注册失效,访问404,后来排查是动态代理导致的。
打印控制层代码
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
@EnableDiscoveryClient
@SpringBootApplication
public class ComplaintApplication {
public static void main(String[] args) throws NoSuchMethodException,InstantiationException,IllegalAccessException, InvocationTargetException {
ConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(ComplaintApplication.class, args);
String[] beans = configurableApplicationContext.getBeanDefinitionNames();
RequestMappingHandlerMapping requestMappingHandlerMapping=configurableApplicationContext.getBean(RequestMappingHandlerMapping.class);
// 获取url与类和方法的对应信息
Map<RequestMappingInfo, HandlerMethod> map = requestMappingHandlerMapping.getHandlerMethods();
for (RequestMappingInfo info : map.keySet()) {
// 获取url的Set集合,一个方法可能对应多个url
Set<String> patterns = info.getPatternsCondition().getPatterns();
for (String url : patterns) {
//把结果存入静态变量中程序运行一次次方法之后就不用再次请求次方法
System.out.println(url);
}
}
for (String bean : beans)
{
System.out.println(bean + " of Type :: " + configurableApplicationContext.getBean(bean).getClass());
}
}
}
userController打印出来的class 是class com.sun.proxy.$Proxy103
解决办法在yml文件添加配置就会去使用cglib的代理
spring:
aop:
auto: false
基于CGLIB的代理与基于JDK的动态代理实现的声明式事务的区别
- CGLIB基于继承实现,JDK动态代理基于实现接口实现
- CGLIB的代理类需要事务注解@Transactional标注在类上(或方法);而JDK动态代理类事务注解@Transactional可以标注在接口上(或方法),也可以标注在实现类上(或方法)
auto | proxy-target-class | proxyTargetClass | 代理技术 | 备注 |
---|---|---|---|---|
true | false | false | JDK动态代理 | |
true | true | false | CGLIB | 默认值 |
true | false | true | CGLIB | |
true | true | true | CGLIB | |
false | false | false | JDK动态代理 | |
false | true | false | JDK动态代理 | |
false | false | true | CGLIB | |
false | true | true | CGLIB |