簡體   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