我正在试验是否可以在邮递员中调用javassist在运行时创建的控制器文件。创建一个Java类,其类上带有@RestController
批注,方法上带有Postmapping批注。不出所料,它无法从邮递员那里打电话。
我的同事说,这可能是因为注释扫描的时机所致。当启动Spring Boot时,会出现如下所示的日志,其中引用了AnnotationConfigApplicationContext
,因此我尝试将Bean注册到AnnotationConfigApplicationContext
,但结果是相同的。未找到。
因此,首先想知道是否有可能。
2019-11-06 15:22:14.825 DEBUG [external-service,,,](20008)[main] [o.s.c.a.AnnotationConfigApplicationContext:590] [local] Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@72be135f
2019-11-06 15:22:14.837 DEBUG [external-service,,,](20008)[main] [o.s.b.f.s.DefaultListableBeanFactory:213] [local] Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
这是用于创建带注释的控制器的代码。
public Class ctClassController() throws Exception {
CtClass ctController = this.createCtClass("ctController");
CtMethod ctMethod = CtNewMethod.make("public String test(){ return 'testController';}", ctController);
ClassFile cFile = ctController.getClassFile();
ConstPool constPool = cFile.getConstPool();
AnnotationsAttribute attr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
Annotation annotation = new Annotation(RestController.class.getName(), constPool);
attr.addAnnotation(annotation);
annotation = new Annotation(Component.class.getName(), constPool);
attr.addAnnotation(annotation);
ctController.getClassFile().addAttribute(attr);
AnnotationsAttribute attr4Method = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
annotation = new Annotation(PostMapping.class.getName(), constPool);
annotation.addMemberValue("value", new StringMemberValue("/api/ctController", constPool));
attr4Method.setAnnotation(annotation);
ctMethod.getMethodInfo().addAttribute(attr4Method);
ctController.addMethod(ctMethod);
ctController.toClass(this.getClass().getClassLoader(), this.getClass().getProtectionDomain());
Class klass = Class.forName("ctController");
return klass;
}
,以下是重新扫描注释的尝试。
Class controllerKlass = vendorDynamicClassConstructor.ctClassController();
Object controllerObj = controllerKlass.getDeclaredConstructor().newInstance();
AbstractApplicationContext abstractContext = new AnnotationConfigApplicationContext();
abstractContext.refresh();
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(controllerObj.getClass());
context.refresh();
因此,如果我这样向邮递员打电话,http://localhost:2028/api/ctController 我想查看“ testController”,但是我得到了以下内容。会有其他方法吗?
<Map>
<timestamp>1573026801879</timestamp>
<status>404</status>
<error>Not Found</error>
<message>No message available</message>
<path>/api/ctController</path>
</Map>