使用Java Config时如何防止Spring生命周期方法?

在返回对象后,如何防止问题服务器上的@PostConstruct方法Spring调用

@Configuration
class MyConfig {
    @Bean
    public ProblematicService problematicService() {
        ProblematicService service = someMethodOutsideMyControl();
        // ProblematicService is constructed for me by other code (outside of Spring)
        // and it happens to have a @PostConstruct method. The @PostConstruct method
        // cannot be invoked here or by Spring once this method returns.
        return service;
    }
}

我相信将结果包装在factorybean中会产生预期的效果,但我需要在几个地方重复这段代码,所以我正在寻找更优雅的解决方案.

最佳答案
这是一个非平凡的变化. @Configuration类(或者更确切地说是AnnotationConfigApplicationContext)注册一个CommonAnnotationBeanPostProcessor,它负责调用bean的@PostConstruct方法.改变这意味着几乎改变整个Spring IoC堆栈.

实际上,您可以使用bean名称org.springframework.context.annotation.internalCommonAnnotationProcessor声明CommonAnnotationBeanPostProcessor,它将覆盖默认名称.您可以将init注释类型设置为null,以便它忽略@PostConstruct.

@Bean(name = "org.springframework.context.annotation.internalCommonAnnotationProcessor")
public CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor() {
    CommonAnnotationBeanPostProcessor bean = new CommonAnnotationBeanPostProcessor();
    bean.setInitAnnotationType(null);;
    return bean;
}

使用它时要小心,否则可能会破坏其他东西.

我将首先建议尝试找到解决方法.例如,返回一个包装器对象,它可以让您访问ProblematicService.

@Bean
public ServiceProvider provider() {
    ProblematicService service = ...;
    ServiceProvider provider = new ServiceProvider(service);
    return provider;
}

或者类似你建议的factorybean.

另一个更酷但更丑陋的方法是将对象包装在CGLIB代理中.

@Bean
public ProblematicService service() {
    ProblematicService service = ...;
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(service.getClass());
    enhancer.setCallback(new MethodInterceptor() {
        ProblematicService inner = service;
        @Override
        public Object intercept(Object obj,Method method,Object[] args,MethodProxy proxy) throws Throwable {
            if (!method.getName().equals("initMethodName"))
                return method.invoke(inner,args);
            return null;
        }
    });
    return (ProblematicService) enhancer.create();
}

基本上,永远不能调用init方法.

相关文章

Spring Cloud为Spring Boot应用程序提供Netflix OSS集成。 提供的功能模块包括服务发现(Eureka),断路...
Spring Cloud 学习笔记;maven配置;入门学习;基于Spring Boot 实现;服务端配置,客户端配置;
可以毫不夸张地说,这篇文章介绍的 Spring/SpringBoot 常用注解基本已经涵盖你工作中遇到的大部分常用的...
Spring中各种方式进行日期时间处理,有作用于单个实体的,也有作用于全局的,有作用于请求入参的,有作...
跨域资源共享(Cross-origin resource sharing)(CORS)是W3C的标准,大部分的浏览器都实现了这个标准...
Spring Boot使创建基于Spring的应用程序变得轻松,大部分的SpringBoot应用程序都只需要很少的Spring配置...