SPRING

SPRING

Alexey Zavyalov

Краткая шпаргалка по Spring.

XML-конфигурация

1. Создать классы POJO

2. Создать context.xml

2.1. Указать классы POJO как бины

2.2. Указать property

3. В методе main создать ApplicationContext context = new ClassPathXmlApplicationContext("context.xml");

4. Получить все необходимые бины через context.getBean([имя_бина]);

4.1. Сделать cast

5. Вызывать у созданного бина необходимые методы


Типы IoC-контейнеров

Spring поддерживает 2 типа IoC-контейнеров

1. BeanFactory (устаревший, легковесный, можно использовать если ресурсы критичны, например на мобильных устройствах) - необходим для обратной совместимости.

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

БИНЫ

Бины - объекты, которые составляют основу (позвоночник) приложения и управляются Spring'ом.

Бин содержит информацию о том:

- Как создать бин

- Детали жизненного цикла бина

- Зависимости бина

Свойства и описание бинов

1. class - определяет класс для создания бина. Обязательный атрибут

2. name - уникальный ID бина

3. scope - определяет круг объектов, созданных на основе этого бина

4. constructor-arg - используется для ввода зависимостей

5. properties - используется для ввода зависимостей

6. autowiring mode - используется для ввода зависимостей

7. lazy-initialization mode - ленивая инициализация говорит IoC-контейнеру создать этот бин при первом запросе, а не при старте

8. initialization method - callback-функция (обратного вызова), которая будет вызвана после того как все необходимые свойства бина будут установлены контейнером

9. destruction method - callback-функция (обратного вызова), которая будет вызвана когда бин в контейнере будет уничтожен

Spring Configuration Metadata

1. XML based configuration file

2. Annotation-based configuration

3. Java-based configuration

SCOPE

1. singleton - спринг будет возвращать один и тот же объект созданного бина

2. prototype - каждый раз будет возвращаться новый объект бина

3. request - один бин на один HTTP-request (только для web-aware ApplicationContext)

4. session - один бин на одну HTTP-сессию (только для web-aware ApplicationContext)

5. global-session - один бин на одну глобальную HTTP-сессию (только для web-aware ApplicationContext)

SCOPE: SINGLETON

scope="singleton"

IoC-контейнер создаст только один экземпляр объекта описанного в определении бина. Этот единственный экземпляр будет храниться в кэше и при каждом запросе будет возвращаться этот экземпляр.

Scope по умолчанию всегда SINGLETON.

SCOPE: PROTOTYPE

scope = "prototype"

IoC-контейнер будет создавать новый экземпляр объекта при каждом новом запросе. Как правило, prototype используют тогда, когда состояние бина полностью "заполнено", а singleton - когда у бина нет состояния.

ЖИЗНЕННЫЙ ЦИКЛ БИНА

Жизненный цикл бина легко понять. Когда создается экземпляр бина, может потребоваться некоторая инициализация, чтобы привести его в полезное состояние. Аналогичным образом, когда бин больше не требуется и удаляется из контейнера, может потребоваться некоторая очистка.

init-method

init-method - указывает метод, который вызывается в бине сразу после создания экземпляра

Метод должен находиться в этом классе.

3 способа задания init-метода:

1. В XML-конфигурации прописать init-method="init" (или другое название) и он будет вызван после создания объекта.

2. Реализовать интерфейс org.springframework.beans.factory.InitializingBean. Он содержит один метод void afterPropertiesSet() throws Exception;, в котором тоже можно прописать действия, которые будут выполнены после создания объекта. В этом случае в XML-конфигурации ничего указывать не надо. Spring сам увидит этот метод и вызовет его.

*3. Навесить на метод аннотацию @PostConctruct (про эту аннотацию более подробно рассказывается далее).

Если указать и init-method и реализовать интерфейс одновременно, то выполнятся оба метода, но afterPropertiesSet() выполнится раньше.

destroy-method

destroy-method - указывает метод, который вызывается непосредственно ПЕРЕД удалением бина из контейнера

То же самое, что и в случае init-method.

Название интерфейса: org.springframework.beans.factory.DisposableBean

*3. Навесить на метод аннотацию @PreDestroy (про эту аннотацию более подробно рассказывается далее).

Если использовать оба способа одновременно, то сначала будет вызван метод из интерфейса.

Default initialization and destroy methods

Если у вас слишком много бинов, которые имеют init() и / или destroy() методы с тем же именем, вам не нужно объявлять метод init-method и destroy-method для каждого отдельного бина. Вместо этого Spring обеспечивает гибкость для настройки такой ситуации с использованием атрибутов default-init-method и default-destroy-method в элементе <beans> следующим образом


<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
default-init-method = "init" 
default-destroy-method = "destroy">

Bean Post Processors

Позволяет заложить свою логику в создание бина.

Для этого необходимо реализовать интерфейс org.springframework.beans.factory.config.BeanPostProcessor, у него есть 2 метода:

- postProcessBeforeInitialization(Object bean, String beanName)

- postProcessAfterInitialization(Object bean, String beanName)

В этих методах и можно записать какие-то свои действия, которые будут выполнены с бином перед его попаданием в IoC-контейнер.

Первым агрументом приходит Object - сам бин, вторым - его имя.

Bean Definition Inheritance (Наследование определения бинов)

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

parent = "helloWorld"

Вы можете создать шаблон определения Bean, который может использоваться другими определениями дочерних бинов. При определении шаблона вы не должны указывать атрибут класса, но должны указать абстрактный атрибут со значением true, как показано в следующем фрагменте кода

<bean id = "beanTeamplate" abstract = "true">
   <property name = "message1" value = "Hello World!"/>
   <property name = "message2" value = "Hello Second World!"/>
   <property name = "message3" value = "Namaste India!"/>
</bean>

Родительский бин не может быть создан, потому что он неполный, и он также явно обозначен как абстрактный. Когда определение является абстрактным, его можно использовать только как шаблон для дочернего бина.

Constructor-based Dependency Injection

<!-- Definition for textEditor bean -->
  <bean id = "textEditor" class = "com.tutorialspoint.TextEditor">
   <constructor-arg ref = "spellChecker" />
  </bean>

  <!-- Definition for spellChecker bean -->
  <bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker" />

  

Контейнер также может использовать сопоставление типов с простыми типами, если вы явно указываете тип аргумента конструктора, используя атрибут type. Например,

  <bean id = "exampleBean" class = "examples.ExampleBean">
   <constructor-arg type = "int" value = "2001"/>
   <constructor-arg type = "java.lang.String" value = "Zara"/>
  </bean>

Ещё один способ передать аргументы конструктора: используйте атрибут index, чтобы явно указать индекс аргументов конструктора. Например,

  <bean id = "exampleBean" class = "examples.ExampleBean">
   <constructor-arg index = "0" value = "2001"/>
   <constructor-arg index = "1" value = "Zara"/>
  </bean>

Наконец, если вы передаете ссылку на объект, вам нужно использовать атрибут ref тега <constructor-arg>, если вы передаете значение напрямую, вы должны использовать атрибут value, как показано выше.

Setter-based Dependency Injection

Всё то же самое, что и в Constructor-based Dependency Injection, за исключением того, что в XML-конфигурации надо указывать не constructor-arg, а property.


  <!-- Definition for textEditor bean -->
  <bean id = "textEditor" class = "com.tutorialspoint.TextEditor">
   <property name = "spellChecker" ref = "spellChecker" />
  </bean>

  <!-- Definition for spellChecker bean -->
  <bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker" />

ВАЖНО!

Название сеттера должно соответствовать конвенции об именовании. Чтобы установить переменную spellChecker, мы используем метод setSpellChecker().

XML Configuration using p-namespace

Если у вас много методов setter, тогда удобно использовать p-namespace в файле конфигурации XML.

БЫЛО:

  <bean id = "john-classic" class = "com.example.Person">
   <property name = "name" value = "John Doe"/>
   <property name = "spouse" ref = "jane"/>
  </bean>

  <bean name = "jane" class = "com.example.Person">
   <property name = "name" value = "John Doe"/>
  </bean>

СТАЛО:

  <bean id = "john-classic" class = "com.example.Person"
   p:name = "John Doe"
   p:spouse-ref = "jane"/>
  </bean>

  <bean name =" jane" class = "com.example.Person"
   p:name = "John Doe"/>
  </bean>

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

Injecting Inner Beans

Как вы знаете, внутренние классы Java определены в рамках других классов, аналогичным образом, внутренние бины - это бины, которые определены в рамках другого бина. Таким образом, элемент <bean /> внутри элементов <property /> или <constructor-arg /> называется внутренним bean-компонентом, и это показано ниже.

  <bean id = "outerBean" class = "...">
   <property name = "target">
     <bean id = "innerBean" class = "..."/>
   </property>
  </bean>

Injecting Collection

Spring предлагает четыре типа элементов конфигурации коллекции:

1. <list> - позволяет инжектить списки значений (позволяет дублировать)

2. <set> - позволяет инжектить наборы значений (без дубликатов)

3. <map> - позволяет инжектить коллекции пар key-value, где key и value могут быть любого типа

4. <props> - позволяет инжектить коллекции пар key-value, где key и value являются строками (String)

СИНТАКСИС СЛЕДУЮЩИЙ:

<bean id="javaCollection" class="pro.spring.collection.JavaCollection">
    <property name="list">
      <list>
        <value>Russia</value>
        <value>USA</value>
        <value>Canada</value>
        <value>China</value>
        <value>Finland</value>
      </list>
    </property>
    <property name="set">
      <set>
        <value>Russia</value>
        <value>USA</value>
        <value>USA</value>
        <value>China</value>
        <value>Finland</value>
      </set>
    </property>
    <property name="map">
      <map>
        <entry key="1" value="Russia" />
        <entry key="2" value="USA" />
        <entry key="3" value="Canada" />
        <entry key="4" value="China" />
        <entry key="5" value="Finland" />
      </map>
    </property>
    <property name="properties">
      <props>
        <prop key="one">Russia</prop>
        <prop key="one">Russia</prop>
        <prop key="two">USA</prop>
        <prop key="three">China</prop>
        <prop key="four">Finland</prop>
      </props>
    </property>
  </bean>

Injecting Bean References

  <!-- Bean Definition to handle references and values -->
  <bean id = "..." class = "...">

   <!-- Passing bean reference for java.util.List -->
   <property name = "addressList">
     <list>
      <ref bean = "address1"/>
      <ref bean = "address2"/>
      <value>Pakistan</value>
     </list>
   </property>
    
   <!-- Passing bean reference for java.util.Set -->
   <property name = "addressSet">
     <set>
      <ref bean = "address1"/>
      <ref bean = "address2"/>
      <value>Pakistan</value>
     </set>
   </property>
    
   <!-- Passing bean reference for java.util.Map -->
   <property name = "addressMap">
     <map>
      <entry key = "one" value = "INDIA"/>
      <entry key = "two" value-ref = "address1"/>
      <entry key = "three" value-ref = "address2"/>
     </map>
   </property>
  </bean>


Injecting null and empty string values

<bean id = "..." class = "exampleBean">
  <property name = "email" value = ""/>
</bean>


То же самое, что и: exampleBean.setEmail("")


<bean id = "..." class = "exampleBean">
  <property name = "email"><null/></property>
</bean>


То же самое, что и: exampleBean.setEmail(null)

Beans Auto-Wiring

Контейнер Spring может создавать Autowiring между взаимодействующими бинами без использования элементов <constructor-arg> и <property>, что помогает сократить объем конфигурации XML, который вы пишете для большого приложения на основе Spring.

Autowiring Modes

1. no - настройка по умолчанию, означает отсутствие Autowiring, нужно использовать явную ссылку на bean

2. byName - Autowiring по названию свойства. Spring смотрит на properties бинов, для которых атрибут autowire установлен в byName в файле конфигурации XML

3. byType - Autowiring по типу данных property. Spring смотрит на properties бинов, для которых атрибут autowire установлен в byType в файле конфигурации XML. Затем он пытается сопоставить и связать свойство, если его тип совпадает с одним из имен бинов в файле конфигурации. Если существует более одного такого компонента, генерируется фатальное исключение.

4. constructor - Подобно byType, но тип применяется к аргументам конструктора. Если в контейнере нет ни одного бина типа аргумента конструктора, возникает фатальная ошибка.

5. autodetect - Spring сначала пытается связать с помощью autowire конструктором, если не получается, то пытается autowire byType.


byType или constructor используется чтобы связать массивы и другие типизированные коллекции.

ОГРАНИЧЕНИЯ

Autowiring работает лучше всего, когда он последовательно используется в проекте. Если Autowiring вообще не используется, разработчикам может быть сложно использовать его для подключения только одного или двух определений бинов. Хотя Autowiring может значительно уменьшить необходимость указания свойств или аргументов конструктора, нужно учитывать ограничения и недостатки Autowiring перед использованием.

1. Возможность переопределения - Вы все же можете указывать зависимости, используя настройки <constructor-arg> и <property>, которые всегда будут переопределять Autowiring.

2. Примитивные типы данных - Вы не можете autowire так называемые простые свойства, такие как примитивы, строки и классы.

3. Запутанность - Autowiring менее точен, чем явное указание, поэтому, если это возможно, предпочитайте использовать явное указание.

Spring Autowiring 'byName', 'byType', constructor

Позволяет явно не указывать названия бинов, которые надо инжектить в другой бин. Вместо этого в определении бина можно указать:

autowire="byName"
autowire="byType"
autowire="constructor"

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

Пример для 'byName':

БЫЛО:

  <!-- Definition for textEditor bean -->
  <bean id = "textEditor" class = "com.tutorialspoint.TextEditor">
   <property name = "spellChecker" ref = "spellChecker" />
   <property name = "name" value = "Generic Text Editor" />
  </bean>

  <!-- Definition for spellChecker bean -->
  <bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker"></bean>

  

СТАЛО:

  <!-- Definition for textEditor bean -->
  <bean id = "textEditor" class = "com.tutorialspoint.TextEditor" autowire = "byName">
   <property name = "name" value = "Generic Text Editor" />
  </bean>

  <!-- Definition for spellChecker bean -->
  <bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker"></bean>

Annotation Based Configuration

Вместо использования XML для описания компоновки бинов, можно переместить конфигурацию бина в сам класс бина, используя аннотации к соответствующему классу, методу или объявлению поля.

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

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


<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
  xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context = "http://www.springframework.org/schema/context"
  xsi:schemaLocation = "http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-3.0.xsd">

  <context:annotation-config/>
  <!-- bean definitions go here -->

</beans>


После настройки <context: annotation-config /> вы можете начать аннотировать свой код. После этого Spring начнет автоматически связывать значения со свойствами, методами и конструкторами.

Некоторые важные аннотации:

1. @Required - Применяется к сеттерам

2. @Autowired - Применяется к сеттерам, не-сеттер методам, конструкторам и properties

3. @Qualifier - Аннотацию @Qualifier вместе с @Autowired можно использовать для устранения путаницы, указав, какой именно бин инжектить

4. JSR-250 Annotations - Spring поддерживает аннотации на основе JSR-250, которые включают аннотации @Resource, @PostConstruct и @PreDestroy

@Required

Говорит, что сеттер ТРЕБУЕТСЯ! Его обязательно нужно заинжектить!

Аннотации @Required применимы к методам set-свойств объекта bean, и указывает на то, что свойство должно быть заполнено в файле конфигурации XML. В противном случае контейнер выдает исключение BeanInitializationException. Ниже приведен пример, показывающий использование @Required аннотации.


public class Student {
  private Integer age;
  private String name;

  @Required
  public void setAge(Integer age) {
   this.age = age;
  }
  public Integer getAge() {
   return age;
  }
  
  @Required
  public void setName(String name) {
   this.name = name;
  }
  public String getName() {
   return name;
  }
}


XML:

  <bean id="student" class="pro.spring.annotations.Student">
    <property name="name" value="Dima" />
    <property name="age" value="20" />
  </bean>

@Autowired

Аннотацию @Autowired можно использовать для связки bean-компонента по методу setter, как @Required, конструктору, свойству или методу с произвольными именами и / или несколькими аргументами.

@Autowired on Setter Methods

Вы можете использовать @Autowired аннотацию по методам setter, чтобы избавиться от элемента <property> в файле конфигурации XML. Когда Spring находит аннотацию @Autowired, используемую с методом setter, то пытается выполнить связку byType в методе.


@Autowired
public void setSpellChecker(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}


@Autowired on Properties

Вы можете использовать @Autowired аннотацию на свойствах, чтобы избавиться от методов setter. Когда вы передаете значения autowired свойств с помощью <property>, Spring автоматически присваивает эти свойства переданным значениям или ссылкам.


@Autowired
private SpellChecker spellChecker;


@Autowired on Constructors

@Autowired на конструкторе указывает, что конструктор должен быть autowired при создании бина, даже если элементы <constructor-arg> НЕ УКАЗАНЫ при настройке компонента в файле XML.


  @Autowired
  public TextEditor(SpellChecker spellChecker){
   System.out.println("Inside TextEditor constructor." );
   this.spellChecker = spellChecker;
  }

  

@Autowired with (required=false) option

По умолчанию аннотация @Autowired подразумевает, что зависимость ТРЕБУЕТСЯ, аналогично аннотации @Required, однако вы можете отключить поведение по умолчанию, используя параметр (required = false) с @Autowired.


  @Autowired(required=false)
  public void setAge(Integer age) {
   this.age = age;
  }

@Qualifier

Может возникнуть ситуация, когда вы создаете более одного бина одного типа и хотите связать только один из них со свойством.

В таких случаях вы можете использовать аннотацию @Qualifier вместе с @Autowired, чтобы удалить путаницу, указав, какой именно компонент будет подключен. Ниже приведен пример использования аннотации @Qualifier.


  @Autowired
  @Qualifier("student1")
  private Student student;

Spring JSR-250 Annotations

Spring также поддерживает аннотации на основе JSR-250, которые включают аннотации @PostConstruct, @PreDestroy и @Resource. Хотя эти аннотации на самом деле не требуются, потому что у вас уже есть другие альтернативы, но давайте кратко изложим их.

@PostConstruct and @PreDestroy Annotations

Чтобы определить установку и "отключение" бина, мы просто объявляем <bean> с параметрами init-method и / или destroy-method. Атрибут init-method указывает метод, который должен быть вызван в bean-компоненте сразу после создания экземпляра. Аналогично, метод destroy указывает метод, который вызывается непосредственно перед удалением компонента из контейнера.

Вы можете использовать аннотацию @PostConstruct в качестве альтернативы функции обратного вызова для инициализации и аннотацию @PreDestroy в качестве альтернативы функции обратного вызова для разрушения, как описано в приведенном ниже примере.

  @PostConstruct
  public void init(){
   System.out.println("Bean is going through init.");
  }
  
  @PreDestroy
  public void destroy(){
   System.out.println("Bean will destroy now.");
  }

После этого необходимо вызвать метод registerShutdownHook(), который объявлен в классе AbstractApplicationContext. Это обеспечит "изящное" (graceful) завершение работы и вызовет соответствующие методы уничтожения.

@Resource Annotation

Вы можете использовать аннотацию @Resource для полей или методов setter, и она работает так же, как в Java EE 5. Аннотации @Resource берут атрибут «имя», который будет интерпретироваться как имя бина, который должен быть заинжектен. Можно сказать, что это следует из семантики autowiring by-name.


  @Resource(name = "spellChecker")
  public void setSpellChecker( SpellChecker spellChecker ){
   this.spellChecker = spellChecker;
  }

  

Если «имя» не указано явно, из имени поля или метода сеттера выводится имя по умолчанию.

- В случае поля - это имя поля;

- В случае сеттера - он принимает имя свойства bean.

Java Based Configuration

Используя конфигурацию Java можно достичь того же результата, как и при использовании XML-конфигурации и Annotation конфигурации. Java-конфигурация позволяет написать большую часть конфигурации Spring без XML, с помощью нескольких Java-аннотаций.

@Configuration & @Bean Annotations

Аннотирование класса @Configuration означает, что класс может использоваться контейнером Spring IoC в качестве источника определений бинов. Аннотирование @Bean сообщает Spring, что метод, аннотированный с помощью @Bean, вернет объект, который должен быть зарегистрирован как бин в Spring application context. Простейший возможный класс @Configuration будет следующим:


@Configuration
public class HelloWorldConfig {
  @Bean 
  public HelloWorld helloWorld(){
   return new HelloWorld();
  }
}


Вышеупомянутый код будет эквивалентен следующей конфигурации XML:


<beans>
  <bean id = "helloWorld" class = "com.tutorialspoint.HelloWorld" />
</beans>


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


public static void main(String[] args) {
  ApplicationContext ctx = new AnnotationConfigApplicationContext(HelloWorldConfig.class);
  
  HelloWorld helloWorld = ctx.getBean(HelloWorld.class);
  helloWorld.setMessage("Hello World!");
  helloWorld.getMessage();
}


Вы можете загружать различные классы конфигурации следующим образом:


public static void main(String[] args) {
  AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();

  ctx.register(AppConfig.class, OtherConfig.class);
  ctx.register(AdditionalConfig.class);
  ctx.refresh();

  MyService myService = ctx.getBean(MyService.class);
  myService.doStuff();
}


Следует отметить, что никаких файлов конфигурации в этом случае не потребуется.


Injecting Bean Dependencies

Если @Bean'ы имеют зависимости друг от друга, то выражается эта зависимость так: один метода бина вызывает другой метод бина.


@Configuration
public class AppConfig {
  @Bean
  public Foo foo() {
   return new Foo(bar());
  }
  @Bean
  public Bar bar() {
   return new Bar();
  }
}


Здесь foo bean получает ссылку на bar через инъекцию конструктора. Теперь давайте посмотрим на другой рабочий пример.


@Configuration
public class TextEditorConfig {
  @Bean 
  public TextEditor textEditor() {
   return new TextEditor(spellChecker());
  }

  @Bean 
  public SpellChecker spellChecker() {
   return new SpellChecker();
  }
}


The @Import Annotation

Аннотация @Import позволяет загружать определения @Bean из другого класса конфигурации. Рассмотрим следующей класс:


@Configuration
public class ConfigA {
  @Bean
  public A a() {
   return new A(); 
  }
}


Вы можете импортировать объявление этого Bean'а в другой класс конфигурации.


@Configuration
@Import(ConfigA.class)
public class ConfigB {
  @Bean
  public B a() {
   return new A(); 
  }
}


Теперь, вместо того, чтобы указывать как ConfigA.class, так и ConfigB.class при создании экземпляра контекста, необходимо настроить только ConfigB следующим образом:


public static void main(String[] args) {
  ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);
  
  // теперь оба бина A и B будут доступны
  A a = ctx.getBean(A.class);
  B b = ctx.getBean(B.class);
}

Report Page