java аннотации - В чем разница между комментариями @Component, @Repository и @Service весной?




spring annotation (21)

Могут ли @Component , @Repository и @Service аннотации использоваться взаимозаменяемо весной или они предоставляют какую-либо конкретную функциональность, помимо того, что вы выступаете в качестве устройства нотации?

Другими словами, если у меня есть класс службы, и я изменяю аннотацию из @Service на @Component , будет ли он по-прежнему вести себя одинаково?

Или аннотация также влияет на поведение и функциональность класса?


Answers

Spring 2.5 вводит дополнительные аннотации к стереотипам: @Component, @Service и @Controller. @Component служит общим стереотипом для любого компонента, управляемого Spring; тогда как @Repository, @Service и @Controller служат специализациями @Component для более конкретных случаев использования (например, в уровнях персистентности, обслуживания и представления соответственно). Это означает, что вы можете комментировать ваши классы компонентов с помощью @Component, но вместо этого добавив их в @Repository, @Service или @Controller, ваши классы более подходят для обработки инструментами или связывания с аспектами. Например, эти аннотации стереотипов делают идеальные цели для pointcut. Конечно, также возможно, что @Repository, @Service и @Controller могут нести дополнительную семантику в будущих выпусках Spring Framework. Таким образом, если вы принимаете решение об использовании @Component или @Service для вашего уровня обслуживания, @Service, безусловно, лучший выбор. Аналогично, как указано выше, @Repository уже поддерживается как маркер автоматического перевода исключений в вашем уровне персистентности.

@Component – Indicates a auto scan component.
@Repository – Indicates DAO component in the persistence layer.
@Service – Indicates a Service component in the business layer.
@Controller – Indicates a controller component in the presentation layer.

reference: - Spring Documentation - Сканирование классов, управляемые компоненты и записи с использованием Java


все эти аннотации относятся к типу типа стереотипа аннотации, разница между этими тремя аннотациями

  • Если мы добавим @Component, тогда он скажет, что роль класса является классом компонента, это означает, что это класс, состоящий из некоторой логики, но он не говорит о том, является ли класс, содержащий определенную бизнес-логику или постоянство или логику контроллера, поэтому мы не используем прямо в этой аннотации @Component
  • Если мы добавим аннотацию @Service, тогда она сообщит, что роль класса, состоящего из бизнес-логики
  • Если мы добавим @Repository поверх класса, тогда он сообщает, что класс, содержащий логику сохранения
  • Здесь @Component - базовая аннотация для аннотаций @ Service, @ Repository и @Controller

например

package com.spring.anno;
@Service
public class TestBean
{
    public void m1()
    {
       //business code
    }
}

package com.spring.anno;
@Repository
public class TestBean
{
    public void update()
    {
       //persistence code
    }
}
  • всякий раз, когда мы добавляем @Service или @Repositroy или @Controller по умолчанию, аннотация @Component собирается существовать поверх класса

@Component - это общая аннотация верхнего уровня, которая заставляет аннотированный компонент быть отсканированным и доступным в контейнере DI

@Repository - это специализированная аннотация, которая привносит особенность преобразования всех исключенных исключений из классов DAO

@Service - специализированная аннотация. он не привносит никакой новой функции на данный момент, но он разъясняет намерение компонента

@Controller - это специализированная аннотация, которая делает bean MVC @RequestMapping и позволяет использовать дополнительную аннотацию, такую ​​как @RequestMapping и все такие

Вот более details


Весной 4, последняя версия:

Аннотирование @Repository является маркером для любого класса, который выполняет роль или стереотип репозитория (также известного как объект доступа к данным или DAO). Среди применений этого маркера - автоматический перевод исключений, как описано в Разделе 20.2.2, «Перевод исключений».

Spring предоставляет дополнительные аннотации к стереотипам: @Component, @Service и @Controller. @Component - это общий стереотип для любого компонента, управляемого Spring. @Repository, @Service и @Controller являются специализациями @Component для более конкретных случаев использования, например, в уровнях персистентности, обслуживания и представления, соответственно. Таким образом, вы можете аннотировать свои классы компонентов с помощью @Component, но вместо этого аннотируя их с помощью @Repository, @Service или @Controller, ваши классы более подходят для обработки инструментами или связывания с аспектами. Например, эти аннотации стереотипов делают идеальные цели для pointcut. Также возможно, что @Repository, @Service и @Controller могут нести дополнительную семантику в будущих выпусках Spring Framework. Таким образом, если вы выбираете между использованием @Component или @Service для вашего уровня обслуживания, @Service, безусловно, лучший выбор. Аналогично, как указано выше, @Repository уже поддерживается как маркер автоматического перевода исключений в вашем уровне персистентности.


Аннотировать другие компоненты с помощью @Component, например, классы ресурсов REST.

@Component
public class AdressComp{
    .......
    ...//some code here    
}

@Component - это общий стереотип для любого компонента, управляемого Spring.

@Controller, @Service и @Repository являются специализациями @Component для конкретных случаев использования.

@Component весной


Поскольку многие ответы уже указывают, для чего используются эти аннотации, мы остановимся на некоторых незначительных различиях между ними.

Сначала сходство

Еще один момент, который стоит подчеркнуть, заключается в том, что в отношении сканирования-автоматического обнаружения и зависимостей для BeanDefinition все эти аннотации (а именно @Component, @Service, @Repository, @Controller) одинаковы. Мы можем использовать один вместо другого и все еще можем обойтись.

Различия между @Component, @Repository, @Controller и @Service

@Составная часть

Это аннотация стереотипа общего назначения, указывающая, что класс является весенним компонентом.

Что особенного в @Component
<context:component-scan> проверяет только @Component и не ищет @Controller , @Service и @Repository в целом. Они сканируются, потому что они сами аннотируются с @Component .

Просто взгляните на @Controller , @Service и @Repository определения аннотаций:

@Component
public @interface Service {
    ….
}

@Component
public @interface Repository {
    ….
}

@Component
public @interface Controller {
    …
}

Таким образом, не стоит говорить, что @Controller , @Service и @Repository являются специальными аннотациями @Component . <context:component-scan> выбирает их и записывает их следующие классы в виде бобов, как если бы они были аннотированы с @Component .

Они сканируются, потому что они сами аннотируются аннотацией @Component . Если мы определим нашу собственную аннотацию и аннотируем ее с помощью @Component , она также будет проверена с помощью <context:component-scan>

@Repository

Это означает, что класс определяет репозиторий данных.

Что особенного в @Repository?

В дополнение к тому, что это конфигурация на основе аннотаций , работа @Repository заключается в том, чтобы улавливать специфические исключения для платформы и повторно бросать их как одно из исключенных исключенных исключений Spring. И для этого нам предоставлен PersistenceExceptionTranslationPostProcessor , который мы должны добавить в контексте приложения Spring, например:

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

Этот обработчик @Repository добавляет советника к любому bean-компоненту, который аннотируется с @Repository так что любые исключения для конкретной платформы пойманы, а затем возвращаются как один из исключенных исключений доступа к данным Spring.

@Controller

Аннотация @Controller указывает, что конкретный класс служит ролью контроллера. @Controller действует как стереотип для аннотированного класса с указанием его роли.

Что особенного в @Controller?

Мы не можем переключать эту аннотацию на любой другой, такой как @Service или @Repository , хотя они выглядят одинаково. Диспетчер просматривает классы, аннотированные с помощью @Controller и обнаруживает в них аннотации @RequestMapping . Мы можем использовать @RequestMapping @Controller аннотированных классов @Controller .

@Обслуживание

@Services содержат бизнес-логику и метод вызова в слое репозитория.

Что особенного в @Service?

Помимо того, что он используется для обозначения того, что он держит бизнес-логику, нет заметной специальности, которую предоставляет эта аннотация, но кто знает, весна может добавить в будущем дополнительные дополнительные возможности.

Что-то еще?

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


@Service чтобы процитировать весеннюю документацию,

Указывает, что аннотированный класс - это «Служба», первоначально определенная Domain-Driven Design (Evans, 2003) как «операция, предлагаемая как интерфейс, который стоит отдельно в модели, без инкапсулированного состояния». Может также указать, что класс - это «Бизнес-фасад» (в смысле ядра J2EE) или что-то подобное. Это аннотирование является стереотипом общего назначения, и отдельные команды могут сузить семантику и использовать по мере необходимости.

Если вы посмотрите на дизайн, управляемый доменом,

СЕРВИС - это операция, предлагаемая в качестве интерфейса, который стоит отдельно в модели, без инкапсулирующего состояния, как это делают объекты и объекты VALUE. УСЛУГИ являются общей схемой в технических рамках, но они также могут применяться на уровне домена. Служба имен подчеркивает взаимосвязь с другими объектами. В отличие от ОБЪЕКТОВ И ОБЪЕКТОВ VALUE, он определяется исключительно с точки зрения того, что он может сделать для клиента. СЛУЖБА имеет тенденцию быть названным для действия, а не для сущности-глагола, а не для существительного. СЕРВИС все еще может иметь абстрактное, преднамеренное определение; у него просто отличный вкус, чем определение объекта. Служба SERVICE должна по-прежнему иметь определенную ответственность, а ответственность и выполняемый интерфейс должны быть определены как часть модели домена. Названия операций должны поступать из UBIQUITOUS LANGUAGE или вводиться в нее. Параметры и результаты должны быть объектами домена. УСЛУГИ следует использовать разумно и не разрешать лишать ОБЪЕКТОВ И ЦЕННОСТЕЙ ОБЪЕКТОВ всех своих действий. Но когда операция на самом деле является важной концепцией домена, СЕРВИС образует естественную часть МОДЕЛЬ-ДВИЖЕНИЯ. Объявленная в модели как служба, а не как фальшивый объект, который на самом деле ничего не представляет, автономная операция никого не вводит в заблуждение.

и Repository в соответствии с Эриком Эвансом,

REPOSITORY представляет все объекты определенного типа в качестве концептуального набора (обычно эмулируемого). Он действует как сборник, за исключением более сложных запросов. Объекты соответствующего типа добавляются и удаляются, а оборудование, расположенное за REPOSITORY, вставляет их или удаляет из базы данных. Это определение собирает сплоченный набор обязанностей для обеспечения доступа к корням AGGREGATES из раннего жизненного цикла до конца.


Нет никакой разницы между @ Component, @ Service, @ Controller, @ Repository. @Component - это общая аннотация для представления компонента нашего MVC. Но в составе нашего MVC-приложения будут использоваться несколько компонентов, таких как компоненты уровня обслуживания, компоненты уровня persistence и компоненты уровня представления. Поэтому, чтобы отличить их, люди весны также дали еще три аннотации.

Представление компонентов уровня сохранения: @Repository

Чтобы представить компоненты уровня обслуживания: @Service

Чтобы представить компоненты уровня презентации: @Controller

или вы можете использовать @Component для всех из них.


Из весны Документация :

В Spring 2.0 и более поздних @Repository аннотация @Repository является маркером для любого класса, который выполняет роль или стереотип (также известный как объект доступа к данным или DAO) репозитория. Среди применений этого маркера - автоматический перевод исключений.

Spring 2.5 вводит дополнительные аннотации к стереотипам: @Component , @Service и @Controller . @Component - это общий стереотип для любого компонента, управляемого Spring. @Repository , @Service и @Controller являются специализациями @Component для более конкретных случаев использования, например, в уровнях персистентности, обслуживания и представления, соответственно.

Таким образом, вы можете аннотировать свои классы компонентов с помощью @Component , но вместо этого аннотируя их с помощью @Repository , @Service или @Controller , ваши классы более подходят для обработки инструментами или связывания с аспектами. Например, эти аннотации стереотипов делают идеальные цели для pointcut.

Таким образом, если вы выбираете между использованием @Component или @Service для вашего уровня обслуживания, @Service , безусловно, лучший выбор. Аналогично, как указано выше, @Repository уже поддерживается как маркер автоматического перевода исключений в вашем уровне персистентности.

┌────────────┬─────────────────────────────────────────────────────┐
│ Annotation │ Meaning                                             │
├────────────┼─────────────────────────────────────────────────────┤
│ @Component │ generic stereotype for any Spring-managed component │
│ @Repository│ stereotype for persistence layer                    │
│ @Service   │ stereotype for service layer                        │
│ @Controller│ stereotype for presentation layer (spring-mvc)      │
└────────────┴─────────────────────────────────────────────────────┘

@Component : вы комментируете класс @Component, он сообщает спящему, что это Bean.

@Repository : вы комментируете класс @Repository, он говорит, что спящий режим является классом DAO и рассматривает его как класс DAO. Означает, что он делает исключенные исключения (брошенные из методов DAO), подходящие для перевода в Spring DataAccessException.

@Service : это говорит о спящем режиме, это класс обслуживания, где у вас будут @Transactional и т. Д. Аннотации уровня сервиса, поэтому hibernate рассматривает его как компонент службы.

Plus @Service продвигается @Component. Предположим, что имя класса компонента - CustomerService, так как вы не выбрали конфигурацию XML-компонента, поэтому вы аннотировали компонент с @Component, чтобы указать его как Bean. Таким образом, при получении объекта компонента CustomerService cust = (CustomerService)context.getBean("customerService"); По умолчанию Spring уменьшит регистр первого символа компонента - от «CustomerService» до «customerService». И вы можете получить этот компонент с именем «customerService». Но если вы используете аннотацию @Service для класса bean, вы можете указать конкретное имя компонента

@Service("AAA")
public class CustomerService{

и вы можете получить объект bean

CustomerService cust = (CustomerService)context.getBean("AAA");

В весеннем каркасе предусмотрен специальный аннотация, называемая аннотациями стереотипов. Они следующие: -

@RestController- Declare at controller level.
@Controller – Declare at controller level.
@Component – Declare at Bean/entity level.
@Repository – Declare at DAO level.
@Service – Declare at BO level.

выше объявленных аннотаций являются особыми, потому что, когда мы добавляем <context:component-scan>в файл xxx-servlet.xml, spring автоматически создаст объект тех классов, которые аннотируются с помощью аннотации в течение фазы создания / загрузки контекста.


Они почти одинаковы - все они означают, что класс - фасоль весны. @Service , @Repository и @Controller - специализированные @Component s. Вы можете выполнять определенные действия с ними. Например:

  • @Controller используются весной-mvc
  • @Repository beans имеют право на перенос исключения настойчивости

Другое дело, что вы условно обозначаете компоненты семантически для разных слоев.

Одна вещь, @Component предлагает @Component заключается в том, что вы можете аннотировать другие аннотации с ней, а затем использовать их так же, как @Service .

Например, недавно я сделал:

@Component
@Scope("prototype")
public @interface ScheduledJob {..}

Таким образом, все классы, аннотированные с помощью @ScheduledJob являются весенними бобами и в дополнение к ним регистрируются как кварцевые задания. Вам просто нужно предоставить код, который обрабатывает конкретную аннотацию.


Репозиторий и служба являются дочерними элементами аннотации компонентов . Итак, все они являются Компонентами . Репозиторий и служба просто расширяют его.Как именно? Сервис имеет только идеологическую разницу: мы используем его для обслуживания. В репозитории имеется специальный обработчик исключений.


Объяснение стереотипов:

  • @Service - аннотировать все ваши классы обслуживания с помощью @Service. Этот слой знает единицу работы. Вся ваша бизнес-логика будет в классах Service. Обычно методы уровня обслуживания покрываются по транзакции. Вы можете сделать несколько вызовов DAO из метода службы, если одна транзакция не удалась, все транзакции должны откат.
  • @Repository - аннотировать все ваши классы DAO с помощью @Repository. Вся логика доступа к базе данных должна быть в классах DAO.
  • @Component - аннотировать ваши другие компоненты (например, классы ресурсов REST) ​​с компонентным стереотипом.
  • @Autowired - пусть Spring автоматически @Autowired другие бобы в ваши классы с помощью @Autowired аннотации.

@Component - это общий стереотип для любого компонента, управляемого Spring. @Repository , @Service и @Controller являются специализациями @Component для более конкретных случаев использования, например, в уровнях персистентности, обслуживания и представления, соответственно.

Первоначально ответил here .


Spring предоставляет четыре разных типа аннотаций автокомпонентного сканирования, они @Component , @Service , @Repository и @Controller . Технически нет никакой разницы между ними, но каждая аннотация для автокомпонентного сканирования должна использоваться для специального назначения и в пределах определенного уровня.

@Component : это базовая аннотация для автокомпонентного сканирования, она указывает, что аннотированный класс является компонентом автоматического сканирования.

@Controller : Аннотированный класс указывает, что он является компонентом контроллера и в основном используется на уровне представления.

@Service : указывает, что аннотированный класс является компонентом службы на бизнес-уровне.

@Repository : вам нужно использовать эту аннотацию в уровне персистентности, это действует как репозиторий базы данных.

Нужно выбрать более специализированную форму @Component , аннотируя их класс, поскольку эта аннотация может содержать определенное поведение в будущем.


Мы можем ответить на это по стандарту java

Ссылаясь на JSR-330 , который теперь поддерживается весной, вы можете использовать @Named для определения компонента ( @Named @[email protected] ). Таким образом, согласно этому стандарту, нет смысла определять стереотипы (например, @Repository , @Service , @Controller ) для категорий beans.

Но весенний пользователь эти разные аннотации в разных для конкретного использования, например:

  1. Помогите разработчикам определить лучшую категорию для компетентных. В некоторых случаях эта категоризация может оказаться полезной. (Например, когда вы используете aspect-oriented , это может быть хорошим кандидатом для pointcuts )
  2. Аннотации @Repository добавят некоторую функциональность вашему bean-компоненту (некоторый автоматический перевод исключений на ваш уровень @Repository компонента).
  3. Если вы используете @RequestMapping MVC, @RequestMapping может быть добавлен только в классы, которые аннотируются @Controller .

@Repository @Service и @Controller служат специализацией @Component для более конкретного использования на этой основе, вы можете заменить @Service на @Component, но в этом случае вы потеряете специализацию.

1. **@Repository**   - Automatic exception translation in your persistence layer.
2. **@Service**      - It indicates that the annotated class is providing a business service to other layers within the application.

Использование аннотаций @Service и @Repository важны с точки зрения подключения к базе данных.

  1. Используйте @Service для всех типов подключений к веб-сервису
  2. Используйте @Repository для всех сохраненных подключений proc DB

Если вы не используете соответствующие аннотации, вы можете столкнуться с исключениями, отмененными транзакциями отката. Вы увидите исключения во время теста нагрузочной нагрузки, связанные с откатными транзакциями JDBC.


Технически @Controller, @Service, @Repository - все те же. Все они расширяют @Components.

Из исходного кода Spring:

Указывает, что аннотированный класс является «компонентом». Такие классы рассматриваются как кандидаты на автоматическое обнаружение при использовании конфигурации на основе аннотаций и сканирования пути к классам.

Мы можем напрямую использовать @Component для каждого компонента, но для лучшего понимания и поддержки большого приложения мы используем @Controller, @Service, @Repository.

Цель каждой аннотации:

1) @Controller -> Классы, аннотированные с этим, предназначены для получения запроса со стороны клиента. Первый запрос поступает в диспетчерский сервлет, откуда он передает запрос конкретному контроллеру, используя значение аннотации @RequestMapping.

2) @Service -> Классы, аннотированные этим, предназначены для управления данными, которые мы получаем от клиента или извлечения из базы данных. Все манипуляции с данными должны выполняться в этом слое.

3) @Repository -> Классы, аннотированные этим, предназначены для подключения к базе данных. Его также можно рассматривать как слой DAO (Data Access Object). Этот слой должен быть ограничен только CRUD (создавать, извлекать, обновлять, удалять). Если требуется какая-либо манипуляция, данные должны быть отправлены обратно на уровень @Service.

Если мы заменим их место (используйте @Repository вместо @Controller), наше приложение будет работать нормально.

Основная цель использования трех разных @annotations - обеспечить лучшую модульность для приложения Enterprise.


@component
@controller
@Repository
@service
@RestController

Это все аннотации StereoType. Если мы разместим @controller поверх класса. Он не станет классом контроллера, основанным на разных слоях (компонентах), которые мы можем аннотировать с помощью этих аннотаций, но компилятор ничего не сделает для этого только для целей понимания разработчика, которые мы можем выбрать на основе компонентов, которые мы должны писать


<context:annotation-config> используется для активации аннотаций в компонентах, уже зарегистрированных в контексте приложения (независимо от того, были ли они определены с помощью XML или сканирования пакетов).

<context:component-scan> также может выполнять то, что <context:annotation-config> , но <context:component-scan> также сканирует пакеты для поиска и регистрации bean-компонентов в контексте приложения.

Я буду использовать некоторые примеры, чтобы показать различия / сходства.

Давайте начнем с базовой установки трех фасонов типа A , B и C , причем B и C вводят в A

package com.xxx;
public class B {
  public B() {
    System.out.println("creating bean B: " + this);
  }
}

package com.xxx;
public class C {
  public C() {
    System.out.println("creating bean C: " + this);
  }
}

package com.yyy;
import com.xxx.B;
import com.xxx.C;
public class A { 
  private B bbb;
  private C ccc;
  public A() {
    System.out.println("creating bean A: " + this);
  }
  public void setBbb(B bbb) {
    System.out.println("setting A.bbb with " + bbb);
    this.bbb = bbb;
  }
  public void setCcc(C ccc) {
    System.out.println("setting A.ccc with " + ccc);
    this.ccc = ccc; 
  }
}

Со следующей конфигурацией XML:

<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A">
  <property name="bbb" ref="bBean" />
  <property name="ccc" ref="cBean" />
</bean>

Загрузка контекста дает следующий результат:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

Хорошо, это ожидаемый результат. Но это «старый стиль» Весны. Теперь у нас есть аннотации, поэтому давайте использовать их для упрощения XML.

Во-первых, давайте autwire свойства bbb и ccc на bean A так:

package com.yyy;
import org.springframework.beans.factory.annotation.Autowired;
import com.xxx.B;
import com.xxx.C;
public class A { 
  private B bbb;
  private C ccc;
  public A() {
    System.out.println("creating bean A: " + this);
  }
  @Autowired
  public void setBbb(B bbb) {
    System.out.println("setting A.bbb with " + bbb);
    this.bbb = bbb;
  }
  @Autowired
  public void setCcc(C ccc) {
    System.out.println("setting A.ccc with " + ccc);
    this.ccc = ccc;
  }
}

Это позволяет мне удалить следующие строки из XML:

<property name="bbb" ref="bBean" />
<property name="ccc" ref="cBean" />

Теперь мой XML упрощен:

<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />

Когда я загружаю контекст, я получаю следующий вывод:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]

Хорошо, это неправильно! Что случилось? Почему мои свойства не поддерживаются?

Ну, аннотации - приятная особенность, но сами по себе они ничего не делают. Они просто комментируют вещи. Вам нужен инструмент обработки, чтобы найти аннотации и сделать что-то с ними.

<context:annotation-config> для спасения. Это активирует действия для аннотаций, которые он находит в компонентах, определенных в том же контексте приложения, где он определен.

Если я изменю свой XML на это:

<context:annotation-config />
<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />

когда я загружаю контекст приложения, я получаю правильный результат:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

Хорошо, это хорошо, но я удалил две строки из XML и добавил один. Это не очень большая разница. Идея с аннотациями заключается в том, что предполагается удалить XML.

Поэтому давайте удалим определения XML и заменим их аннотациями:

package com.xxx;
import org.springframework.stereotype.Component;
@Component
public class B {
  public B() {
    System.out.println("creating bean B: " + this);
  }
}

package com.xxx;
import org.springframework.stereotype.Component;
@Component
public class C {
  public C() {
    System.out.println("creating bean C: " + this);
  }
}

package com.yyy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.xxx.B;
import com.xxx.C;
@Component
public class A { 
  private B bbb;
  private C ccc;
  public A() {
    System.out.println("creating bean A: " + this);
  }
  @Autowired
  public void setBbb(B bbb) {
    System.out.println("setting A.bbb with " + bbb);
    this.bbb = bbb;
  }
  @Autowired
  public void setCcc(C ccc) {
    System.out.println("setting A.ccc with " + ccc);
    this.ccc = ccc;
  }
}

Хотя в XML мы сохраняем это:

<context:annotation-config />

Мы загружаем контекст, и результат ... Ничего. Никакие бобы не создаются, никакие бобы не автоусиливаются. Ничего такого!

Это потому, что, как я сказал в первом абзаце, <context:annotation-config /> работает только с компонентами, зарегистрированными в контексте приложения. Поскольку я удалил XML-конфигурацию для трех компонентов, нет никакого bean-компонента, и <context:annotation-config /> не имеет «целей» для работы.

Но это не проблема для <context:component-scan> которая может сканировать пакет для «целей» для работы. Давайте изменим содержимое конфигурации XML на следующую запись:

<context:component-scan base-package="com.xxx" />

Когда я загружаю контекст, я получаю следующий вывод:

creating bean B: [email protected]
creating bean C: [email protected]

Хммм ... чего-то не хватает. Зачем?

Если вы посмотрите на классы, класс A имеет пакет com.yyy но я указал в <context:component-scan> чтобы использовать пакет com.xxx так что это полностью пропустило мой класс A и только подобрало B и C которые находятся в пакете com.xxx .

Чтобы исправить это, я также добавлю этот другой пакет:

<context:component-scan base-package="com.xxx,com.yyy" />

и теперь мы получаем ожидаемый результат:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

И это все! Теперь у вас больше нет определений XML, у вас есть аннотации.

В качестве окончательного примера, сохраняя аннотированные классы A , B и C и добавляя следующее в XML, что мы получим после загрузки контекста?

<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />

Мы по-прежнему получаем правильный результат:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

Даже если bean для класса A не получается путем сканирования, инструменты обработки все еще применяются <context:component-scan> для всех компонентов, зарегистрированных в контексте приложения, даже для A который был зарегистрирован вручную в XML.

Но что, если у нас есть следующий XML, получим ли мы дублированные компоненты, потому что мы указали как <context:annotation-config /> и <context:component-scan> ?

<context:annotation-config />
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />

Нет, нет дубликатов. Мы снова получаем ожидаемый результат:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

Это связано с тем, что оба <context:annotation-config /> регистрируют одни и те же инструменты обработки ( <context:annotation-config /> может быть опущен, если указан параметр <context:component-scan> ), но Spring позаботится об их запуске только один раз.

Даже если вы регистрируете инструменты обработки самостоятельно несколько раз, Spring все равно будет удостовериться, что они делают свою магию только один раз; этот XML:

<context:annotation-config />
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />
<bean id="bla" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla1" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla2" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla3" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />

будет по-прежнему генерировать следующий результат:

creating bean B: [email protected]
creating bean C: [email protected]4a87
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

Хорошо, это о разрыве.

Я надеюсь, что эта информация вместе с ответами @Tomasz Nurkiewicz и @Sean Patrick Floyd - все, что вам нужно, чтобы понять, как работают <context:annotation-config> и <context:component-scan> .







java spring spring-mvc annotations