Spring: @Компонент против @Bean
Я понимаю, что в spring 2.5 была введена аннотация @Component
, чтобы избавиться от определения xml bean, используя сканирование классов.
@Bean
был введен в spring 3.0 и может использоваться с @Configuration
, чтобы полностью избавиться от xml файла и использовать java-конфигурацию вместо этого.
Возможно ли повторное использование аннотации @Component
вместо введения аннотации @Bean
? Я понимаю, что конечной целью является создание beans в обоих случаях.
Ответы
Ответ 1
@Component
и @Bean
делают две совершенно разные вещи, и их не следует путать.
@Component
(и @Service
и @Repository
) используются для автоматического обнаружения и автоматической настройки beans с помощью сканирования пути к классам. Существует неявное взаимно однозначное сопоставление между аннотированным классом и bean (т.е. Один bean для каждого класса). Управление проводкой довольно ограничено этим подходом, поскольку оно чисто декларативное.
@Bean
используется для явного объявления одного bean, а не для Spring делать это автоматически, как указано выше. Он отделяет объявление bean от определения класса и позволяет вам создавать и настраивать beans точно, как вы выбираете.
Чтобы ответить на ваш вопрос...
возможно ли повторное использование аннотации @Component
вместо введения аннотации @Bean
?
Конечно, возможно; но они решили не делать этого, так как они совершенно разные. Spring уже сбивает с толку, не загромождая воды далее.
Ответ 2
@Component
Предназначен для сканирования компонентов и автоматической проводки.
Когда вы должны использовать @Bean?
Иногда автоматическая настройка не является опцией. Когда? Представьте, что вы хотите подключать компоненты из сторонних библиотек (у вас нет исходного кода, поэтому вы не можете комментировать его классы с помощью @Component), поэтому автоматическая настройка невозможна,
@Bean аннотация возвращает объект, который spring должен регистрироваться как bean в контексте приложения. тело метода несет логику, ответственную за создание экземпляра.
Ответ 3
Давайте рассмотрим, я хочу конкретную реализацию в зависимости от некоторого динамического состояния. @Bean
идеально подходит для этого случая.
@Bean
@Scope("prototype")
public SomeService someService() {
switch (state) {
case 1:
return new Impl1();
case 2:
return new Impl2();
case 3:
return new Impl3();
default:
return new Impl();
}
}
Однако это невозможно сделать с помощью @Component
.
Ответ 4
Оба подхода нацелены на регистрацию целевого типа в контейнере Spring.
Разница в том, что @Bean
применим к методам, тогда как @Component
применим к типам.
Поэтому, когда вы используете аннотацию @Bean
, вы управляете логикой создания экземпляра в теле метода (см. пример выше). С аннотацией @Component
вы не можете.
Ответ 5
- @Component автоматически обнаруживает и настраивает bean-компоненты, используя сканирование пути к классам, тогда как @Bean явно объявляет один bean-компонент, а не позволяет Spring делать это автоматически.
- @Component не отделяет объявление bean-компонента от определения класса, а @Bean отделяет объявление bean-компонента от определения класса.
- @Component - это аннотация уровня класса, где @Bean - это аннотация уровня метода, а имя метода служит именем компонента.
- @Component не нужно использовать с аннотацией @Configuration, где аннотация @Bean должна использоваться внутри класса, аннотируемого @Configuration.
- Мы не можем создать bean-компонент класса, используя @Component, если класс находится вне контейнера Spring, тогда как мы можем создать bean-компонент класса, используя @Bean, даже если класс присутствует вне контейнера Spring.
- @Component имеет различные специализации, такие как @Controller, @Repository и @Service, тогда как @Bean не имеет специализаций.
Ответ 6
@Component Это общая аннотация, которая может быть применена к любому классу приложения, чтобы сделать его компонентом с пружинным управлением (просто, общий стереотип для любого компонента с пружинным управлением). когда путь к классу сканируется функцией компонентного сканирования springs (@ComponentScan), он идентифицирует классы, аннотированные аннотацией @Component (в данном пакете), создает компоненты таких классов и регистрирует их в ApplicationContext. @Component - это аннотация уровня класса, цель которой - сделать класс управляемым пружиной компонентом и автоматически обнаруживаемым компонентом для функции сканирования путей к классам.
Если вы хотите узнать больше о @Component и других аннотациях стереотипа, рекомендуем взглянуть на эту статью.
@Bean используется для явного объявления и регистрации bean-компонента (в качестве bean-компонента конфигурации) в контейнере Spring IOC, который возвращается из метода. @Bean - это аннотация уровня метода, и она используется в классе, аннотированном @Configuration. Проще говоря, аннотация @Bean используется для регистрации компонента, возвращаемого методом, в качестве компонента конфигурации пружины в контейнере IOC. @Bean - это только аннотация уровня метода, и ее нельзя использовать с классами и объявлением объекта.
Аннотация @Bean указывает, что метод создает компонент, которым должен управлять контейнер Spring.
Чтобы объявить бин, просто аннотируйте метод аннотацией @Bean. Когда JavaConfig встречает такой метод, он выполняет этот метод и регистрирует возвращаемое значение как компонент в ApplicationContext. По умолчанию имя компонента будет таким же, как имя метода. Ниже приведен простой пример объявления метода @Bean.
@Configuration
public class ApplicationConfig {
@Bean
public User adminUserProfile() {
return new User("Rami","Nassar");
}
}
В классе ApplicationConfig вы можете видеть, что сначала мы используем аннотацию @Configuration, чтобы сообщить Spring, что это файл конфигурации на основе Java. После этого аннотация @Bean используется для объявления bean-компонента Spring и требований DI. Аннотация @Bean эквивалентна тэг, имя метода эквивалентно атрибуту id внутри тег. Я надеюсь, что после прочтения этой статьи вы получите четкое представление о реальной цели и использовании аннотаций @Bean и @Component.
Ответ 7
Когда вы используете тег @Component
, он аналогичен наличию POJO (Plain Old Java Object) с методом объявления ванильного компонента (с аннотацией @Bean
). Например, следующий метод 1 и 2 даст тот же результат.
Способ 1
@Component
public class SomeClass {
private int number;
public SomeClass(Integer theNumber){
this.number = theNumber.intValue();
}
public int getNumber(){
return this.number;
}
}
с бобом для 'theNumber':
@Bean
Integer theNumber(){
return new Integer(3456);
}
Способ 2
//Note: no @Component tag
public class SomeClass {
private int number;
public SomeClass(Integer theNumber){
this.number = theNumber.intValue();
}
public int getNumber(){
return this.number;
}
}
с бобами для обоих:
@Bean
Integer theNumber(){
return new Integer(3456);
}
@Bean
SomeClass someClass(Integer theNumber){
return new SomeClass(theNumber);
}
Метод 2 позволяет вам сохранять объявления bean-компонентов вместе, он немного более гибок и т.д. Вы можете даже захотеть добавить другой не-vanilla bean-компонент SomeClass, как показано ниже:
@Bean
SomeClass strawberryClass(){
return new SomeClass(new Integer(1));
}
Ответ 8
- @component и его специализации (@Controller, @service, @repository) позволяют автоматически обнаруживать с помощью сканирования путей к классам. Если мы увидим класс компонента, такой как @Controller, @service, @repository будет автоматически сканироваться средой Spring с использованием сканирования компонента.
- @Bean, с другой стороны, может использоваться только для явного объявления одного компонента в классе конфигурации.
- @Bean раньше явно объявлял один бин, а не давал Spring делать это автоматически. Это делает отдельное объявление bean-компонента из определения класса.
- Короче говоря, @Controller, @service, @repository предназначены для автоопределения, а @Bean - для создания отдельного компонента из класса.
- @Controller
public class LoginController
{ --code-- }
- @Configuration
public class AppConfig {
@Bean
public SessionFactory sessionFactory()
{--code-- }
Ответ 9
У вас есть два способа создания бобов. Одним из них является создание класса с аннотацией @Component
. Другой - создать метод и аннотировать его с помощью @Bean
. Те классы, которые содержат метод с @Bean
должны быть аннотированы с помощью @Configuration
После запуска проекта @ComponentScan
класс с аннотацией @ComponentScan
будет сканировать каждый класс с @Component
и восстанавливать экземпляр этого класса в контейнере Ioc. Другая вещь, @ComponentScan
должен сделать @ComponentScan
, - это запуск методов с @Bean
и восстановление возвращаемого объекта в контейнер Ioc в виде компонента. Поэтому, когда вам нужно решить, какой тип бобов вы хотите создать, в зависимости от текущих состояний, вам нужно использовать @Bean
. Вы можете написать логику и вернуть нужный объект. Еще одна вещь, которую стоит упомянуть - это имя метода с @Bean
- это имя по умолчанию для bean-компонента.
Ответ 10
@Bean был создан, чтобы не связывать Spring и ваши бизнес-правила во время компиляции. Это означает, что вы можете повторно использовать свои бизнес-правила в других средах, таких как PlayFramework или JEE.
Более того, у вас есть полный контроль над тем, как создавать bean-компоненты, когда этого недостаточно для стандартной реализации Spring.
Я написал пост об этом.
https://coderstower.com/2019/04/23/factory-methods-decoupling-ioc-container-abstraction/
Ответ 11
Я вижу много ответов, и почти везде упомянутый @Component предназначен для автоматического подключения, когда компонент сканируется, а @Bean точно объявляет, что bean-компонент будет использоваться по-другому. Позвольте мне показать, как это отличается.
Сначала это аннотация уровня метода. Во-вторых, вы обычно используете для настройки bean-компонентов в java-коде (если вы не используете конфигурацию xml), а затем вызываете его из класса, используя метод getBean ApplicationContext. лайк
@Configuration
class MyConfiguration{
@Bean
public User getUser(){
return new User();
}
}
class User{
}
//Getting Bean
User user = applicationContext.getBean("getUser");
Это общий способ аннотировать бин, а не специализированный бин. Аннотация уровня класса и используется, чтобы избежать всей этой вещи конфигурации через конфигурацию java или xml.
Мы получаем что-то вроде этого.
@Component
class User {
}
//to get Bean
@Autowired
User user;
Это. Это было просто введено, чтобы избежать всех шагов настройки для создания экземпляра и использования этого компонента.
Ответ 12
Вы можете использовать @Bean
чтобы сделать существующий сторонний класс доступным для контекста приложения Spring Framework.
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
Используя аннотацию @Bean
, вы можете обернуть сторонний класс (он может не иметь @Component
и не может использовать Spring), как бин Spring. И затем, когда он обернут с помощью @Bean
, он становится одноэлементным объектом и доступен в контексте приложения Spring Framework. Теперь вы можете легко поделиться/повторно использовать этот компонент в своем приложении, используя внедрение зависимостей и @Autowired
.
Так что подумайте о аннотации @Bean
- обертке/адаптере для сторонних классов. Вы хотите, чтобы сторонние классы были доступны для контекста приложения Spring Framework.
Используя @Bean
в приведенном выше коде, я явно объявляю один компонент, потому что внутри метода я явно создаю объект, используя ключевое слово new
. Я также вручную вызываю методы установки данного класса. Так что я могу изменить значение поля префикса. Так что эта ручная работа называется явным созданием. Если я использую @Component
для того же класса, боб, зарегистрированный в контейнере Spring, будет иметь значение по умолчанию для поля префикса.
С другой стороны, когда мы аннотируем класс с помощью @Component
, нам не нужно вручную использовать ключевое слово new
. Он обрабатывается автоматически Spring.