如何在春季启动中使用应用程序上下文获取 bean

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

ControllerA

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

如果有人知道解决办法,请帮忙。

339270 次浏览

可以将 ApplicationContext 自动连接为字段

@Autowired
private ApplicationContext context;

或者一种方法

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

终于派上用场了

context.getBean(SomeClass.class)

如果您位于 Springbean (在本例中为 @Controllerbean)内部,则根本不应该使用 Spring 上下文实例。直接自动连接 className bean。

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

你可以使用 ApplicationContextAware

ApplicationContextAware :

接口,该接口由希望获得通知的任何对象实现 实现这个接口 例如,当一个对象需要访问一组 合作的豆子。

有几种方法可以获取对应用程序上下文的引用。您可以像下面的示例一样实现 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 实例化 bean时,它寻找 ApplicationContextAware实现,如果找到了,就会调用 setApplicationContext ()方法。

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

Spring 的 source code代码片段:

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

一旦获得了对 Application 上下文的引用,就可以通过使用 getBean ()获取任何您想要的 bean。

实际上,您希望从 Spring 引擎获得对象,在 Spring 应用程序开始时,该引擎已经维护了所需类的对象(初始化 Spring 引擎)。现在你只需要把这个对象放到一个引用中。

在一个服务类

@Autowired
private ApplicationContext context;


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

现在在 sc 的引用中,你得到了对象。 希望解释得很好。如果有任何疑问请让我知道。

您可以使用 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);
}

可以使用可以提供应用程序上下文的 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);
}
}
}


}

使用:

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()
}

即使在添加了@Autowire (如果您的类不是 RestController 或 Configuration 类)之后,applicationContext 对象仍然是 null。尝试使用以下命令创建新类,效果良好:

@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)对我很有效。例如:

@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)

在配置类中调用 BEAN 注释方法的简单方法。是的,你没听错—— : P 调用 SpringBoot@Bean 方法从 config 返回相同的 bean。我试图从一个 bean 中调用配置类中@prebroke 方法中的注销,并直接调用该方法来获取相同的 bean。 附注: 我在@bean 注释的方法中添加了 debug,但是即使我调用它,它也没有进入方法。当然要怪—— > 春天的魔力 < ——

作为一种替代方法,您可以使用 ConfigurableApplicationContext来获取任何用 @Component@Repository@Service注释的类的 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);
}
}