После моей последней статьи были некоторые вопросы о том, как подробно работает конфигурация Java, и мы можем расширить ее в соответствии с нашими потребностями. Поэтому я постараюсь ответить на эти вопросы в этом посте ?
Механизм конфигурации Java в основе Spring — классы @Configuration . Это место, где мы можем определить все свойства нашего контекста Spring.
Предполагая, что наше приложение опирается на аннотации (что должно быть верно, если мы хотим использовать конфигурацию java), мы создаем bean-компоненты с использованием аннотации @Component (с производными, такими как @Repository , @Service и @Controller ). Различные аннотации применяются для разных слоев:
@Составная часть | универсальный для любых компонентов |
@Repository | персистентный слой |
@Обслуживание | уровень обслуживания |
@Составная часть | уровень представления |
Компонентное сканирование
После аннотирования обязательных классов мы теперь хотим добавить их в контекст Spring. Для достижения этой цели мы должны аннотировать наш @Configuration класс по @ComponentScan :
@Configuration @ComponentScan("my.package.containing.beans") public class SpringConfig { }
В этом случае стоит рассмотреть использование строковых литералов, представляющих пакеты, — легко допустить ошибку, которую трудно найти, потому что даже такие причудливые IDE, как IntelliJ, не заметят совершенную опечатку. К счастью, эта аннотация предлагает безопасную альтернативу, которая позволяет нам использовать параметр basePackageClasses, чтобы указать, например, интерфейс маркера, лежащий в желаемом пакете.
По умолчанию @ComponentScan включает только упомянутые ранее аннотации, но мы можем легко расширить его, чтобы использовать любую пользовательскую аннотацию, например, @ConventionSucks :). Просто нужно добавить элемент includeFilters :
@Configuration @ComponentScan(basePackageClasses = BeansPackageMarker.class, includeFilters = @ComponentScan.Filter(ConventionSucks.class)) public class SpringConfig { }
@ ComponentScan.Filter очень универсален и позволяет использовать различные стратегии по типу ( FilterType ):
АННОТАЦИЯ | помечены данной аннотацией |
ASSIGNABLE_TYPE | присваивается данному типу |
AspectJ | Шаблон типа AspectJ, переданный атрибутом pattern |
REGEX | использует класс Pattern с переданным атрибутом pattern |
CUSTOM | пользовательский фильтр, реализующий TypeFilter |
Те же фильтры можно применять к атрибуту excludeFilters . У нас есть еще один атрибут, который обрабатывает фильтрацию — useDefaultFilters включает импорт всех объектов, аннотированных @Component производными)
Проводка бобов
Теперь мы знаем, как настроить Spring для распознавания наших bean-компонентов, но мы до сих пор не рассмотрели тему об определении зависимостей bean-компонентов (связывание bean-компонентов). Здесь можно выделить два случая:
- бобы, которые мы создали (у нас есть полный контроль)
- внешние бобы
Пользовательские бины
@Component public class UserBeanB { private final UserBeanA userBeanA; @Autowired public UserBeanB(UserBeanA userBeanA) { this.userBeanA = userBeanA; } }
Мы можем использовать аннотацию @Autowired для конструкторов, полей, методов и аннотаций. Существует много дискуссий о том, как лучше внедрить зависимости, но мы не будем говорить об этом в этом посте.
Вместо специфической для Spring аннотации @Autowired мы можем использовать @Inject, представленный в JSR-330 .
Внешние бобы
Это особенно важно, когда мы интегрируем некоторые внешние фреймворки или библиотеки (например, SpringSecurity)
@Configuration public class SpringConfig { @Bean public ExternalObjectA externalObjectA() { return new ExternalObjectA(); } @Bean public ExternalObjectB externalObjectB1() { return new ExternalObjectB(externalObjectA()); } @Bean public ExternalObjectB externalObjectB2() { return new ExternalObjectB(externalObjectA()); } }
Обратите внимание, что аннотация @Bean в методе externalObjectA () очень важна, даже если вы не используете этот компонент вне своего класса конфигурации. Если вы примените аннотацию @Bean, Spring во время загрузки контекста обнаружит ее и вызовет этот метод только один (даже если мы будем использовать его много раз при настройке наших bean-компонентов). Без этой аннотации метод будет рассматриваться как обычный метод Java. Также помните, что имя метода также будет использоваться как имя компонента.
Соединение разных конфигураций
Нередко при внедрении Spring Java Config возникает ситуация, когда мы хотим расширить работающее приложение (например, введя новый модуль) или очистить текущую конфигурацию, удалив явно объявленные bean-компоненты. Также в реальных решениях мы предпочитаем иметь несколько источников конфигурации, а не просто большое большое приложение в одном гигантском классе. В такой ситуации то, что объединяет множество конфигураций, становится необходимым. Весна приносит два решения:
И все — ничего странного;)