Внедрение beans в класс вне управляемого контекста Spring
Я являюсь конечным пользователем одного из своих продуктов компании. Он не очень подходит для интеграции в Spring, однако я могу получить дескриптор контекста и получить требуемый bean по имени. Тем не менее, мне все равно хотелось бы знать, можно ли вводить bean в этот класс, хотя класс не управляется самим Spring.
Разъяснение: то же приложение, которое управляет жизненным циклом некоторого класса MyClass, также управляет жизненным циклом контекста Spring. Spring не имеет никакого знания экземпляра MyClass, и я хотел бы, чтобы каким-то образом предоставлял экземпляр контексту, но не смог создать экземпляр в самом контексте.
Ответы
Ответ 1
Вы можете сделать это:
ApplicationContext ctx = ...
YourClass someBeanNotCreatedBySpring = ...
ctx.getAutowireCapableBeanFactory().autowireBeanProperties(
someBeanNotCreatedBySpring,
AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, true);
Вы можете использовать @Autowired
и т.д. в YourClass
, чтобы указать вводимые поля и т.д.
Ответ 2
предположим, что u имеет следующую цепочку зависимостей:
A → B → C → x → y → Z
A, B, C управляются spring beans (создаются и управляются инфраструктурой spring)
x, y - действительно простые POJO, созданные вашим приложением без помощи spring
теперь, если вы хотите, чтобы y получал ссылку на Z, используя spring, что вам нужно иметь "дескриптор" для spring ApplicationContext
один из способов сделать это - реализовать ApplicationContextAware интерфейс. В этом случае я бы предположил, что либо A, B, либо C реализует этот интерфейс и сохранит ссылку applicationContext в статическом члене.
поэтому давайте возьмем класс C, например:
class C implmenets ApplicationContextAware{
public static ApplicationContex ac;
void setApplicationContext(ApplicationContext applicationContext) {
ac = applicationContext;
}
.............
}
теперь, в классе y вы должны иметь:
(Z)(C.ac.getBean("classZ")).doSomething()
HTH - Yonatan
Ответ 3
Поиск бесконечных комбо-вложений autwire spring bean в pojo applicationcontextaware beanaware и т.д. обменивал меня назад, но это не обеспечило мне достаточно полного решения.
Это намного лучшая реализация/учебник этой ИМО:
Надеюсь, это поможет всем, как это, наконец, помогло мне.
Доступ к spring Beans извне spring Контекст
Ответ 4
Другой способ сделать это - использовать AspectJ. Это рекомендуемый способ инъекции Spring beans в не управляемые объекты, созданные с помощью оператора new
. Подробнее см. Здесь:
http://www.javacodegeeks.com/2011/02/domain-driven-design-spring-aspectj.html
Ответ 5
Один из способов принести bean в Spring, несмотря на то, что его изготовление является внешним, заключается в использовании класса-помощника, помеченного как @Configuration
bean, который имеет метод (помеченный @Bean
), который фактически делает экземпляр и передает его обратно через Spring (который делает свою инъекцию свойств и создание прокси в этой точке).
Я не совсем уверен, какой объем вам нужен; с prototype
, вы получите свежий bean в каждом месте.
@Configuration
public class FooBarMaker {
@Bean(autowire = Autowire.BY_TYPE)
@Scope("prototype")
public FooBar makeAFooBar() {
// You probably need to do some more work in here, I imagine
return new FooBar();
}
}
Вы можете ввести свойства, необходимые для изготовления, в @Configuration
bean. (Я использую это для создания экземпляров интерфейса, где имя экземпляра для экземпляра определяется во время выполнения.)
Ответ 6
Будьте осторожны, что в самой старой версии Spring существует проблема с потоком с bean factory http://jira.springframework.org/browse/SPR-4672
Ответ 7
Если вы хотите создать объект вне контекста Spring и сделать этот объект доступным для вставки в другой beans, который находится в контексте Spring, вы можете выполнить шаги в в этой статье.
В принципе, вы создаете контекст родительского приложения и вставляете свой внешний объект в этот родительский контекст как одноэлементный. Затем вы создаете основной контекст приложения (например, из xml файлов), а родительский контекст приложения - его родительский.
Object externalObject = ...
GenericApplicationContext parent = new StaticApplicationContext();
parent.getBeanFactory().registerSingleton( "externalObject", externalObject );
parent.refresh();
ApplicationContext appContext = new ClassPathXmlApplicationContext( ... , parent);