Spring IoC контейнер: наследование определения бина

Определение бина может содержать много информации о конфигурации, включая аргументы конструктора, значения свойств и информацию, специфичную для контейнера, такую ​​как метод инициализации, имя метода статической фабрики и т. д. Определение дочернего бина наследует данные конфигурации из родительского определения. Дочернее определение может переопределять некоторые значения или добавлять другие при необходимости. Использование определений родительских и дочерних компонентов может сэкономить много времени при вводе. По сути, это форма шаблонов.

Если вы работаете с интерфейсом ApplicationContext программно, определения дочерних бинов представляются классом ChildBeanDefinition. Большинство пользователей не работают с ними на этом уровне. Вместо этого они настраивают определения bean-компонентов декларативно в классе, таком как ClassPathXmlApplicationContext. При использовании метаданных конфигурации на основе XML вы можете указать определение дочернего компонента, используя атрибут parent, указав родительский компонент в качестве значения этого атрибута. В следующем примере показано, как это сделать:

<bean id="inheritedTestBean" abstract="true"
        class="org.springframework.beans.TestBean">
    <property name="name" value="parent"/>
    <!-- обратите внимание на parent атрибут -->
    <property name="age" value="1"/>
</bean>

<bean id="inheritsWithDifferentClass"
        class="org.springframework.beans.DerivedTestBean"
        parent="inheritedTestBean" init-method="initialize">  
    <property name="name" value="override"/>
    <!-- значение свойства age 1 будет унаследовано от parent -->
</bean>

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

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

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

В предыдущем примере явным образом помечается определение родительского компонента как абстрактного с использованием атрибута abstract. Если в родительском определении не указан класс, необходимо явно пометить определение родительского компонента как абстрактное, как показано в следующем примере:

<bean id="inheritedTestBeanWithoutClass" abstract="true">
    <property name="name" value="parent"/>
    <property name="age" value="1"/>
</bean>

<bean id="inheritsWithClass" class="org.springframework.beans.DerivedTestBean"
        parent="inheritedTestBeanWithoutClass" init-method="initialize">
    <property name="name" value="override"/>
    <!-- age будет наследовать значение 1 из определения родительского компонента-->
</bean>

Родительский (parent) компонент не может быть создан самостоятельно, потому что он неполон, и он также явно помечен как абстрактный. Когда определение является абстрактным, его можно использовать только как определение чистого шаблонного компонента, которое служит родительским определением для дочерних определений. Попытка использовать такой абстрактный родительский компонент самостоятельно, путем ссылки на него как свойство ref другого компонента или явный вызов getBean() с идентификатором родительского компонента возвращает ошибку. Аналогично, внутренний метод preInstantiateSingletons() контейнера игнорирует определения компонентов, которые определены как абстрактные.

ApplicationContext предварительно создает все экземпляры по умолчанию. Следовательно, важно (по крайней мере, для одноэлементных компонентов), если у вас есть определение (родительского) компонента, которое вы собираетесь использовать только в качестве шаблона, и в этом определении указан класс, вы должны обязательно установить для абстрактного атрибута значение true в противном случае контекст приложения фактически (попытается) предварительно создаст экземпляр абстрактного компонента.


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


Комментарии

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

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

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

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