简体   繁体   English

将运行时生成的类 bean 添加到 spring boot 应用程序上下文

[英]Add runtime generated class bean to spring boot application context

I am working on a project where I generate a class after the spring boot context starts and compile it to the target/classes folder.我正在开发一个项目,在 spring boot 上下文启动后生成一个类并将其编译到 target/classes 文件夹中。 I know Spring scans the package and registers all the beans in the application context when the application starts.我知道 Spring 会在应用程序启动时扫描包并在应用程序上下文中注册所有 bean。 But here, we are generating a class with annotation @Service at runtime, and the application context is unaware of this new bean.但是在这里,我们在运行时生成一个带有注解 @Service 的类,应用程序上下文不知道这个新 bean。 So, other beans cannot find this runtime-generated class.因此,其他 bean 无法找到这个运行时生成的类。

When I rerun the application, this runtime-generated bean gets registered in the application context, and other beans can utilize that bean.当我重新运行该应用程序时,这个运行时生成的 bean 会在应用程序上下文中注册,其他 bean 可以使用该 bean。 I want to register this runtime-generated bean to the application context without restarting/rerunning the application.我想在不重新启动/重新运行应用程序的情况下将这个运行时生成的 bean 注册到应用程序上下文。

I tried this, but it did not work for me.我试过了,但对我不起作用。

@RestController
@Scope("prototype")
@Slf4j
public class myClass {

    @Autowired
    private ApplicationContext appContext;

    @GetMapping("/beanRegistration")
    public void beanRegistration() {
        try {
            Class<?> generatedClass = Class.forName("myApp.sam.protocompiler.GrpcServerImpl");
            log.info("generatedClass : {} | Methods count: {} | Super class : {}", generatedClass.getCanonicalName(), generatedClass.getMethods().length, generatedClass.getSuperclass());

            ConfigurableListableBeanFactory beanFactory = ((ConfigurableApplicationContext) appContext).getBeanFactory();
            beanFactory.registerSingleton(generatedClass.getCanonicalName(), generatedClass);

            String[] beans = appContext.getBeanDefinitionNames();
            Arrays.sort(beans);
            for (String bean : beans) {
                if(bean.contains(generatedClass.getCanonicalName())) {
                    System.out.println("New Bean : " + bean);
                }
            }
        } catch (Exception ex) {
            log.error("Error : {}", ex.getMessage(), ex);
        }
    }
}

Since you are definitely in a Web application, you might try using GenericWebApplicationContext instead.由于您肯定在 Web 应用程序中,因此您可以尝试使用GenericWebApplicationContext

@Autowired private GenericWebApplicationContext context;

Then,然后,

context.registerBean(generatedClass.getCannonicalName(), generatedClass);

I don't know if this does anything different than what you have, but I think it is the more spring-approved way to do it.我不知道这是否与您所拥有的有什么不同,但我认为这是更受春季认可的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM