Spring IoC контейнер: BeanFactory или ApplicationContext

В этом посте объясняются различия между уровнями контейнеров BeanFactory и ApplicationContext и их влияние на загрузку.

Вам следует использовать ApplicationContext, если у вас нет веских причин для этого, с GenericApplicationContext и его подклассом AnnotationConfigApplicationContext в качестве общих реализаций для настраиваемой начальной загрузки. Это основные точки входа в основной контейнер Spring для всех общих целей: загрузка файлов конфигурации, запуск сканирования пути к классам, программная регистрация определений компонентов и аннотированных классов и (начиная с версии 5.0) регистрация определений функциональных компонентов.

Поскольку ApplicationContext включает в себя все функциональные возможности BeanFactory, его обычно рекомендуется использовать вместо простого BeanFactory, за исключением сценариев, где необходим полный контроль над обработкой bean-компонентов. Внутри ApplicationContext (например, реализации GenericApplicationContext) несколько видов bean-компонентов обнаруживаются по соглашению (то есть по имени bean-компонента или по типу bean-компонента - в частности, постпроцессорам), в то время как простой DefaultListableBeanFactory не зависит от каких-либо специальных bean-компонентов.

Для многих расширенных функций контейнера, таких как обработка аннотаций и проксирование AOP, важна точка расширения BeanPostProcessor. Если вы используете только обычный DefaultListableBeanFactory, такие постпроцессоры не обнаруживаются и не активируются по умолчанию. Эта ситуация может сбивать с толку, потому что на самом деле с вашей конфигурацией bean-компонента все в порядке. Скорее, в таком сценарии контейнер должен быть полностью загружен с помощью дополнительной настройки.

В следующей таблице перечислены функции, предоставляемые интерфейсами и реализациями BeanFactory и ApplicationContext.

Функция
BeanFactory
ApplicationContext
Создание экземпляра компонента/подключение Да Да
Интегрированное управление жизненным циклом Нет Да
Автоматическая регистрация BeanPostProcessor Нет Да
Автоматическая регистрация BeanFactoryPostProcessor Нет Да
Удобный доступ к MessageSource (для интернализации) Нет Да
Встроенный механизм публикации ApplicationEvent Нет Да

Чтобы явно зарегистрировать постпроцессор bean-компонента в DefaultListableBeanFactory, вам необходимо программно вызвать addBeanPostProcessor, как показано в следующем примере:

Java

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// заполняем фабрику определениями bean-компонентов

// теперь регистрируем все необходимые экземпляры BeanPostProcessor
factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
factory.addBeanPostProcessor(new MyBeanPostProcessor());

// теперь начинаем использовать фабрику

Kotlin

val factory = DefaultListableBeanFactory()
// заполняем фабрику определениями bean-компонентов

// теперь регистрируем все необходимые экземпляры BeanPostProcessor
factory.addBeanPostProcessor(AutowiredAnnotationBeanPostProcessor())
factory.addBeanPostProcessor(MyBeanPostProcessor())

// теперь начинаем использовать фабрику

Чтобы применить BeanFactoryPostProcessor к простому DefaultListableBeanFactory, вам необходимо вызвать его метод postProcessBeanFactory, как показано в следующем примере:

Java

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));

// вводим некоторые значения свойств из файла Properties
PropertySourcesPlaceholderConfigurer cfg = new PropertySourcesPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));

// теперь фактически делаем замену
cfg.postProcessBeanFactory(factory);

Kotlin

val factory = DefaultListableBeanFactory()
val reader = XmlBeanDefinitionReader(factory)
reader.loadBeanDefinitions(FileSystemResource("beans.xml"))

// вводим некоторые значения свойств из файла Properties
val cfg = PropertySourcesPlaceholderConfigurer()
cfg.setLocation(FileSystemResource("jdbc.properties"))

// теперь фактически делаем замену
cfg.postProcessBeanFactory(factory)

В обоих случаях явные шаги регистрации неудобны, поэтому различные варианты ApplicationContext предпочтительнее простого DefaultListableBeanFactory в приложениях с поддержкой Spring, особенно при использовании экземпляров BeanFactoryPostProcessor и BeanPostProcessor для расширенных функций контейнера в типичной корпоративной настройке.

AnnotationConfigApplicationContext имеет все зарегистрированные постпроцессоры общих аннотаций и может вводить дополнительные процессоры под крышками через аннотации конфигурации, такие как @EnableTransactionManagement. На уровне абстракции модели конфигурации Spring, основанной на аннотациях, понятие постпроцессоров компонентов становится простой внутренней деталью контейнера.


Читайте также:


Комментарии

Популярные сообщения из этого блога

Методы класса Object в Java

Как получить текущий timestamp в Java

Основные опции JVM для повышения производительности и отладки