Как получить bean-компонент с использованием контекста приложения при загрузке весны
Я занимаюсь разработкой проекта SpringBoot и хочу получить компонент по имени с помощью applicationContext
. Я пробовал многие решения из Интернета, но не смог добиться успеха. Мое требование заключается в том, что у меня есть контроллер
ControllerA
и внутри контроллера у меня есть метод getBean(String className)
. Я хочу получить экземпляр зарегистрированного боба. У меня есть спящие сущности, и я хочу получить экземпляр компонента, передавая имя класса только в методе getBean
.
Пожалуйста, помогите, если кто-то знает решение.
Ответы
Ответ 1
Вы можете Autowire ApplicationContext, либо в качестве поля
@Autowired
private ApplicationContext context;
или метод
@Autowired
public void context(ApplicationContext context) { this.context = context; }
Наконец, используйте
context.getBean(SomeClass.class)
Ответ 2
Вы можете использовать ApplicationContextAware.
ApplicationContextAware:
Интерфейс, который должен быть реализован любым объектом, который хочет получить уведомление о запуске ApplicationContext. Реализация этого интерфейса имеет смысл, например, когда объект требует доступа к набору взаимодействующих компонентов.
Существует несколько способов получения ссылки на контекст приложения. Вы можете реализовать 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 устанавливает текущий контекст приложения.
Фрагмент кода из source code
Spring:
private void invokeAwareInterfaces(Object bean) {
.....
.....
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
}
}
Как только вы получите ссылку на контекст приложения, вы получите выборку bean-компонента по вашему желанию с помощью getBean().
Ответ 3
на самом деле вы хотите получить объект из движка Spring, где движок уже поддерживает объект вашего требуемого класса при запуске приложения Spring (инициализация движка Spring). Теперь дело в том, что вам просто нужно получить этот объект в ссылка.
в классе обслуживания
@Autowired
private ApplicationContext context;
SomeClass sc = (SomeClass)context.getBean(SomeClass.class);
теперь в ссылке sc у вас есть объект. Надеюсь, объяснил хорошо. Если есть сомнения, пожалуйста, дайте мне знать.
Ответ 4
Если вы находитесь внутри Spring bean (в данном случае компонента @Controller
), вы не должны использовать экземпляр контекста Spring вообще. Просто напрямую className
атрибут className
.
BTW, избегайте использования инъекции на месте, поскольку это считается плохой практикой.
Ответ 5
Вы можете использовать класс 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);
}
}
}
}
Ответ 6
Просто используйте:
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()
}
Ответ 7
Вы можете использовать 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);
}