JAVA-6-[Spring Framework] Объем и жизненный цикл компонента

1 весенняя фасоль

1、Spring有两种类型bean,一种普通bean,另外一种工厂bean(FactoryBean)2、普通bean:在配置文件中定义的bean类型就是返回的类型。
3、工厂bean:在配置文件中定义的bean类型可以和返回类型不一样。
第一步 创建类,让这个类作为工厂bean,实现接口FactoryBean
第二步 实现接口里面的方法,在实现的方法中定义返回的bean类型

1.1 Происхождение названия бина

Объекты, управляемые контейнером Spring IoC, называются bean-компонентами, и bean-компоненты создаются в соответствии с информацией в файле конфигурации Spring.

Вы можете думать о контейнере Spring IoC как о большой фабрике. Bean-компоненты эквивалентны продуктам фабрики. Если вы хотите, чтобы эта большая фабрика производила bean-компоненты и управляла ими, вам нужно сообщить контейнеру, какие bean-компоненты необходимы и как собрать бобы.
1. Происхождение названия JAVA
Когда Java была впервые изобретена компанией Sun, она называлась не Java, а Oak (дуб). Название Oak названо в честь дуба возле офиса Джеймса Гослинга, одного из изобретателей Java. Видно, как небрежно они были, когда назвали его.
вставьте сюда описание изображения

К сожалению, вскоре они обнаружили, что название Oak уже было зарегистрировано в качестве товарного знака другими компаниями, поэтому им пришлось создать другое название. Какое имя лучше? В то время они долго спорили и, наконец, выбрали имя «Ява» из нескольких имен-кандидатов.

Почему вы выбрали Java в качестве названия? Это не говоря уже о том, что автор часто упоминает, жители Запада любят использовать для названия контент, связанный с едой. Кроме того, схемы мозга этих программистов в то время были очень странными: название Java ассоциировалось с горячим кофе в офисе. Исторически сложилось так, что в 1696 году, когда голландцы колонизировали Индонезию, саженцы кофе начали распространяться в Джакарте, нынешней столице Индонезии. После этого люди лихорадочно высаживали кофейные саженцы в Индонезии и поставляли их в Европу. Позже остров Ява в Индонезии был богат кофе. Из-за репутации кофе, производимого на острове, слово «Ява» легко связать с кофе. Так родилось название языка программирования Java.

Интересно, что из-за такого наименования Java, когда позже Java EE сменила название, она сменила название на Jakarta EE. Джакарта сейчас столица Индонезии. Поэтому основатели Ява, не имевшие кровного родства с Индонезией, использовали ряд имен, связанных с Индонезией.

Также из-за этого имени многие вещи, связанные с Java, использовали имена, связанные с кофейными зернами, такие как NetBeans, Beans in Spring и т. д.
Во-вторых, происхождение Бин
вставьте сюда описание изображения

Bean — это очень простое понятие в среде Spring, и слово bean означает «бобы» на английском языке. Судя по фактическому использованию Bean в среде Spring, кажется, что они не имеют ничего общего друг с другом, так почему же такое название?
Бин представляет собой базовую единицу в фреймворке Spring.Почти все предустановленные объекты в фреймворке Spring являются своего рода «Бином».Различная обработка данных также выполняется в модулях Бин, а также пользовательские данные. в bean-компонент, прежде чем он может быть обработан.

С одной стороны, если bean-компонент назван в соответствии с его фактическим значением в среде Spring, он должен быть назван в честь таких слов, как «элемент» и «юнит». Но проблема в том, что такие слова, как «элемент», «единица», «атом» и «компонент» стали или могут стать именами собственными в области компьютерных областей, если при таком именовании может возникнуть «неоднозначность». конфликты.

С другой стороны, жители Запада любят называть вещи в честь еды и питья. «Фасоль» также можно рассматривать как основной ингредиент в общественном питании.

1.2 Конфигурационный файл Spring

Файлы конфигурации Spring поддерживают два формата: формат файла XML и формат файла свойств.
(1) Конфигурационный файл свойств в основном существует в виде пар ключ-значение.Он может только присваивать значения и не может выполнять другие операции.Он подходит для простой конфигурации свойств.

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

1. Обычно файлы конфигурации Spring используют формат XML .

XML配置文件的根元素是<beans>,该元素包含了多个子元素<bean>。
每一个<bean>元素都定义了一个Bean,
并描述了该Bean如何被装配到Spring容器中。

Во-вторых, пример файла Beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <bean id="helloWorld123" class="net.biancheng.HelloWorld">
        <property name="message" value="Hello World! Testing" />
    </bean>
</beans>

вставьте сюда описание изображения

2 Область действия компонента

При определении bean-компонента в Spring вы должны объявить параметры области bean-компонента. Например, чтобы заставить Spring создавать новый экземпляр компонента каждый раз, когда это необходимо, вы должны объявить свойство области действия компонента как прототип. Точно так же, если вы хотите, чтобы Spring возвращал один и тот же экземпляр компонента каждый раз, когда это необходимо, вы должны объявить свойство области действия компонента как singleton.

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

Обратите внимание, что три из них доступны, если вы используете ApplicationContext с поддержкой Интернета.
вставьте сюда описание изображения

2.1 одноэлементная область видимости

Синглтон является областью действия по умолчанию, то есть при определении компонента, если элемент конфигурации области не указан, областью действия компонента по умолчанию является синглтон.
Когда областью действия bean-компонента является Singleton, в контейнере Spring IoC будет только один общий экземпляр bean-компонента, и все запросы к bean-компоненту будут возвращать только один и тот же экземпляр bean-компонента, если идентификатор соответствует определению bean-компонента.

То есть, когда для определения bean-компонента задана одноэлементная область, контейнер Spring IoC создаст только единственный экземпляр определения bean-компонента.

Синглтон — это тип синглтона, то есть при создании контейнера одновременно автоматически создается объект-бин, независимо от того, используете вы его или нет, он существует, и объект, получаемый каждый раз, — это один и тот же объект. Обратите внимание, что область Singleton является областью по умолчанию в Spring. Вы можете установить для свойства scope значение singleton в файле конфигурации bean-компонента следующим образом:

<!-- A bean definition with singleton scope -->
<bean id="..." class="..." scope="singleton">
    <!-- collaborators and configuration for this bean go here -->
</bean>

Файл MainApp.java

package net.biancheng;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        HelloWorld objA = (HelloWorld) context.getBean("helloWorld123");
        objA.setMessage("I am A");
        objA.getMessage();
        HelloWorld objB = (HelloWorld) context.getBean("helloWorld123");
        objB.getMessage();
    }
}

Выведите следующую информацию:

Your Message : I'm object A
Your Message : I'm object A

2.2 объем прототипа

Когда областью действия bean-компонента является Prototype, это означает, что определение bean-компонента соответствует нескольким экземплярам объекта. Bean-компоненты с областью действия прототипа вызывают создание нового экземпляра bean-компонента каждый раз, когда запрашивается bean-компонент (путем внедрения его в другой bean-компонент или программным вызовом метода getBean() контейнера).

Prototype — это тип прототипа, он не создается, когда мы создаем контейнер, но объект создается, когда мы получаем bean-компонент, и объекты, которые мы получаем каждый раз, не являются одним и тем же объектом. Как правило, вы должны использовать область прототипа для bean-компонентов с состоянием и область singleton для bean-компонентов без сохранения состояния.

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

<!-- A bean definition with singleton scope -->
<bean id="..." class="..." scope="prototype">
   <!-- collaborators and configuration for this bean go here -->
</bean>

Файл Beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">

    <bean id="helloWorld123" class="net.biancheng.HelloWorld" scope="prototype">
        <property name="message" value="Hello World! Testing" />
    </bean>

</beans>

Результат выглядит следующим образом:

message : I am A
message : Hello World! Testing

3 Жизненный цикл бобов

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

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

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

Жизненный цикл бина можно выразить следующим образом: определение бина — инициализация бина — использование бина — уничтожение бина

4.3.1 Обратный вызов инициализации

(1) Метод 1

通过org.springframework.beans.factory.InitializingBean接口提供下面的方法:
void afterPropertiesSet() throws Exception;
可以简单地实现上述接口和初始化工作可以在afterPropertiesSet()方法中执行,如下所示:
public class ExampleBean implements InitializingBean {
    
    
   public void afterPropertiesSet() {
    
    
      // do some initialization work
   }
}

(2) Метод 2

在基于XML的配置元数据的情况下,可以使用init-method属性来指定带有void无参数方法的名称。
例如:
<bean id="exampleBean" class="examples.ExampleBean" init-method="init"/>
下面是类的定义:
public class ExampleBean {
    
    
   public void init() {
    
    
      // do some initialization work
   }
}

4.3.2 Обратный вызов уничтожения

(1) Метод 1

org.springframework.beans.factory.DisposableBean 接口提供下面的方法:
void destroy() throws Exception;
因此,可以简单地实现上述接口并且结束工作可以在destroy()方法中执行,如下所示:
public class ExampleBean implements DisposableBean {
    
    
   public void destroy() {
    
    
      // do some destruction work
   }
}

(2) Метод 2

在基于XML的配置元数据的情况下,可以使用destroy-method属性来指定带有void无参数方法的名称。例如:
<bean id="exampleBean" class="examples.ExampleBean" destroy-method="destroy"/>
下面是类的定义:
public class ExampleBean {
    
    
   public void destroy() {
    
    
      // do some destruction work
   }
}

Примечание. Если вы используете контейнер Spring IoC в среде, отличной от веб-приложений,
например, в многофункциональной клиентской среде рабочего стола, вам необходимо зарегистрировать перехватчики завершения работы в JVM.
Это обеспечивает корректное завершение работы путем вызова метода destroy для отдельных bean-компонентов, чтобы освободить все ресурсы
.

4.3.3 Пример кода

(1) Файл HelloWorld.java

package net.biancheng;

public class HelloWorld {
    
    
    private String message;

    public void setMessage(String message) {
    
    
        this.message = message;
    }

    public void getMessage() {
    
    
        System.out.println("message : " + message);
    }

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

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

package net.biancheng;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class MainApp {
    
    
    public static void main(String[] args) {
    
    
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        HelloWorld obj = (HelloWorld) context.getBean("helloWorld123");
        obj.getMessage();
        context.registerShutdownHook();
    }
}

(3) Файл Beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">

    <bean id="helloWorld123" class="net.biancheng.HelloWorld"
          init-method="init" destroy-method="destroy">
        <property name="message" value="Hello World! Testing" />
    </bean>

</beans>

Вывод после запуска

Bean is going through init.
message : Hello World! Testing
Bean will destroy now.

4.3.4 Методы инициализации и уничтожения по умолчанию

Если у вас слишком много bean-компонентов с методами инициализации или уничтожения с одинаковыми именами, вам не нужно объявлять методы инициализации и уничтожения для каждого bean-компонента.
Платформа обеспечивает гибкость настройки этой ситуации с использованием атрибутов default-init-method и default-destroy-method для элемента следующим образом:

<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 id="..." class="...">
       <!-- collaborators and configuration for this bean go here -->
   </bean>

</beans>

4.4 Постпроцессор

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

Можно настроить несколько интерфейсов BeanPostProcessor, а порядком выполнения этих интерфейсов BeanPostProcessor можно управлять, установив свойство order, предоставляемое интерфейсом Ordered, реализованным BeanPostProcessor.

BeanPostProcessor может работать с экземплярами bean-компонентов (или объектов), что означает, что контейнер Spring IoC создает экземпляр bean-компонента, а интерфейсы BeanPostProcessor выполняют свою работу.

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

В вашем пользовательском классе реализации интерфейса BeanPostProcessor вам необходимо реализовать следующие два абстрактных метода BeanPostProcessor.postProcessBeforeInitialization(Object, String) и BeanPostProcessor.postProcessAfterInitialization(Object, String)​, обратите внимание на точное наименование.

В противном случае появятся такие ошибки, как: «Тип InitHelloWorld должен реализовать унаследованный абстрактный метод BeanPostProcessor.postProcessBeforeInitialization(Object, String)».
(1) Файл HelloWorld.java

package net.biancheng;

public class HelloWorld {
    
    
    private String message;

    public void setMessage(String message) {
    
    
        this.message = message;
    }

    public void getMessage() {
    
    
        System.out.println("message : " + message);
    }

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

(2) Файл InitHelloWorld.java
Это очень простой пример реализации BeanPostProcessor, который вводит имя bean-компонента до и после инициализации любого bean-компонента . Вы можете реализовать более сложную логику до и после инициализации бина, поскольку у вас есть два метода доступа к пост-обработчику встроенного объекта бина.

package net.biancheng;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.BeansException;
public class InitHelloWorld implements BeanPostProcessor {
    
    
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    
        System.out.println("BeforeInitialization : " + beanName);
        return bean;  // you can return any other object as well
    }
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    
    
        System.out.println("AfterInitialization : " + beanName);
        return bean;  // you can return any other object as well
    }
}

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

package net.biancheng;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class MainApp {
    
    
    public static void main(String[] args) {
    
    
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        HelloWorld obj = (HelloWorld) context.getBean("helloWorld123");
        obj.getMessage();
        context.registerShutdownHook();
    }
}

(4) Файл Beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">

    <bean id="helloWorld123" class="net.biancheng.HelloWorld"
          init-method="init" destroy-method="destroy">
        <property name="message" value="Hello World! Testing" />
    </bean>
    <bean class="net.biancheng.InitHelloWorld" />
</beans>

Вывод после запуска

BeforeInitialization : helloWorld123
Bean is going through init.
AfterInitialization : helloWorld123
message : Hello World! Testing
Bean will destroy now.

4.5 Определение наследования

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

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

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

Когда вы используете метаданные конфигурации на основе XML, вы указываете определение дочернего компонента с помощью родительского свойства, указывая родительский компонент в качестве значения свойства.

рекомендация

отblog.csdn.net/qq_20466211/article/details/129653982