繁体   English   中英

如何在 Spring Boot 中使用应用程序上下文获取 bean

[英]How to get bean using application context in spring boot

我正在开发一个 SpringBoot 项目,我想使用applicationContext通过它的名字来获取 bean。 我从网上尝试了很多解决方案,但都没有成功。 我的要求是我有一个控制器

ControllerA

在控制器内部,我有一个方法getBean(String className) 我想获取已注册 bean 的实例。 我有休眠实体,我想通过只在getBean方法中传递类的名称来获取 bean 的实例。

如果有人知道解决方案,请帮助。

您可以自动装配 ApplicationContext,或者作为一个字段

@Autowired
private ApplicationContext context;

或方法

@Autowired
public void context(ApplicationContext context) { this.context = context; }

最后使用

context.getBean(SomeClass.class)

您可以使用ApplicationContextAware

应用上下文感知

由任何希望被通知它运行的 ApplicationContext 的对象实现的接口。例如,当一个对象需要访问一组协作 bean 时,实现这个接口是有意义的。

有几种方法可以获取对应用程序上下文的引用。 您可以按照以下示例实现 ApplicationContextAware:

package hello;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
 
@Component
public class ApplicationContextProvider implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    } 

 public ApplicationContext getContext() {
        return applicationContext;
    }
    
}

更新:

Spring 实例化 beans 时,它会查找ApplicationContextAware实现,如果找到,将调用 setApplicationContext() 方法。

通过这种方式,Spring 正在设置当前的应用程序上下文。

Spring source code代码片段:

private void invokeAwareInterfaces(Object bean) {
        .....
        .....
 if (bean instanceof ApplicationContextAware) {                
  ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
   }
}

一旦获得对应用程序上下文的引用,就可以使用 getBean() 获取所需的 bean。

实际上,您想从 Spring 引擎获取对象,其中引擎已经在 Spring 应用程序启动时维护了所需类的对象(Spring 引擎的初始化)。现在,您只需要获取该对象即可一个参考。

在服务类中

@Autowired
private ApplicationContext context;

SomeClass sc = (SomeClass)context.getBean(SomeClass.class);

现在在您拥有对象的 sc 的参考中。 希望解释得很好。 如果有任何疑问,请告诉我。

如果您在 Spring bean(在本例中为@Controller bean)内部,则根本不应使用 Spring 上下文实例。 直接自动装配className bean。

顺便说一句,避免使用字段注入,因为它被认为是不好的做法。

您可以使用可以提供应用程序上下文的 ApplicationContextAware 类。

public class ApplicationContextProvider implements ApplicationContextAware {

    private static ApplicationContext ctx = null;

    public static ApplicationContext getApplicationContext() {
        return ctx;
    }

    @Override
    public void setApplicationContext(final ApplicationContext ctx) throws BeansException {
        ApplicationContextProvider.ctx = ctx;
    }

    /**
     * Tries to autowire the specified instance of the class if one of the specified
     * beans which need to be autowired are null.
     *
     * @param classToAutowire        the instance of the class which holds @Autowire
     *                               annotations
     * @param beansToAutowireInClass the beans which have the @Autowire annotation
     *                               in the specified {#classToAutowire}
     */
    public static void autowire(Object classToAutowire, Object... beansToAutowireInClass) {
        for (Object bean : beansToAutowireInClass) {
            if (bean == null) {
                ctx.getAutowireCapableBeanFactory().autowireBean(classToAutowire);
            }
        }
    }

}

即使在添加 @Autowire 之后,如果您的类不是 RestController 或 Configuration Class,applicationContext 对象也会为空。 尝试使用下面的创建新类,它工作正常:

@Component
public class SpringContext implements ApplicationContextAware{

   private static ApplicationContext applicationContext;

   @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws 
     BeansException {
    this.applicationContext=applicationContext;
   }
 }

然后,您可以根据获取 bean 的需要在同一个类中实现一个 getter 方法。 喜欢:

    applicationContext.getBean(String serviceName,Interface.Class)

使用SpringApplication.run(Class<?> primarySource, String... arg)对我SpringApplication.run(Class<?> primarySource, String... arg) 例如:

@SpringBootApplication
public class YourApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(YourApplication.class, args);

    }
}

当我不确定 bean 名称是org.springframework.beans.factory.ListableBeanFactory#getBeanNamesForType(java.lang.Class<?>)时,我使用的一种 API 方法。 我简单地将类类型传递给它,它会为我检索一个 bean 列表。 您可以根据需要检索与该类型及其子类型关联的所有 bean,具体或通用,例如

@Autowired
ApplicationContext ctx

...

SomeController controller = ctx.getBeanNamesForType(SomeController)

作为替代方法,您可以使用ConfigurableApplicationContext获取任何用@Component@Repository@Service注释的@Component bean。

假设您想要获取BaseComponent类的 bean:

@Service
public class BaseComponent {
    public String getMessage() {
        return "hello world";
    }
}

现在您可以使用ConfigurableApplicationContext来获取 bean:

@Component
public class DemoComponent {
    @Autowired
    ConfigurableApplicationContext applicationContext;
    
    public BaseComponent getBeanOfBaseComponent() {
        return applicationContext.getBean(BaseComponent.class);
    }
}

在配置类中调用 BEAN 注释方法的简单方法。 是的,你没听错---- :P 调用 SpringBoot @Bean 注释方法从 config 返回相同的 bean。我试图从 bean 调用配置类中的 @predestroy 方法中的注销,并直接调用该方法以获得相同的结果豆角,扁豆 。 PS:我在@bean 注释的方法中添加了调试,但即使我调用它也没有进入该方法。当然要怪 -----> Spring Magic <----

您可以使用 ServiceLocatorFactoryBean。 首先你需要为你的类创建一个接口

public interface YourClassFactory {
    YourClass getClassByName(String name);
}

然后你必须为 ServiceLocatorBean 创建一个配置文件

@Configuration
@Component
public class ServiceLocatorFactoryBeanConfig {

    @Bean
    public ServiceLocatorFactoryBean serviceLocatorBean(){
        ServiceLocatorFactoryBean bean = new ServiceLocatorFactoryBean();
        bean.setServiceLocatorInterface(YourClassFactory.class);
        return bean;
    }
}

现在你可以通过这样的名字找到你的班级

@Autowired
private YourClassfactory factory;

YourClass getYourClass(String name){
    return factory.getClassByName(name);
}

只需使用:

org.springframework.beans.factory.BeanFactory#getBean(java.lang.Class)

例子:

@Component
public class Example {

    @Autowired
    private ApplicationContext context;

    public MyService getMyServiceBean() {
        return context.getBean(MyService.class);
    }

    // your code uses getMyServiceBean()
}

暂无
暂无

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

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