предисловие
На самом деле это вопрос для собеседования. Он был задан, когда я проходил собеседование для Baidu. Я не ответил на него тогда (потому что у меня это хорошо получалось). Позже я искал ответ в Интернете, но я растерялся, когда увидел.В книге "Весна в действии" есть общее объяснение цикла объявления Bean, но нет разбора кода, поэтому ищу информацию в интернете, и обязательно разбираюсь в жизненном цикле Bean!
Большинство проверенных бинов в интернете находятся в жизненном цикле вопросов интервью.На самом деле в JDK есть полный жизненный цикл бина,что тоже подтверждает односторонность книги.Самая свежая информация- обратитесь к оригинальному JDK!!!
Во-первых, полный жизненный цикл Bean
В традиционных Java-приложениях жизненный цикл bean-компонента очень прост: используйте ключевое слово Java new для создания экземпляра bean-компонента, после чего bean-компонент можно использовать. Как только bean-компонент больше не используется, он автоматически удаляется Java.
Напротив, жизненный цикл управляемых компонентов Spring намного сложнее. Очень важно правильно понимать жизненный цикл компонентов, потому что управление компонентами Spring очень масштабируемо. Ниже показан процесс создания компонента.
Жизненный цикл фасоли
Как показано на рисунке выше, жизненный цикл бина относительно сложен.Давайте опишем каждый шаг на рисунке выше текстом:
- Spring запускает, находит и загружает bean-компоненты, которыми должен управлять Spring, и создает экземпляры bean-компонентов.
- После создания экземпляра компонента введение и значение компонента вводятся в свойства компонента.
- Если Bean реализует интерфейс BeanNameAware, Spring передает идентификатор Bean в метод setBeanName().
- Если Bean реализует интерфейс BeanFactoryAware, Spring вызовет метод setBeanFactory() и передаст экземпляр контейнера BeanFactory.
- Если компонент реализует интерфейс ApplicationContextAware, Spring вызовет метод setApplicationContext() компонента и передаст ссылку контекста приложения, в котором находится компонент.
- Если компоненты реализуют интерфейс BeanPostProcessor, Spring вызовет их метод postProcessBeforeInitialization().
- Если Бин реализует интерфейс InitializingBean, Spring вызовет их метод afterPropertiesSet(). Точно так же, если бин объявляет метод инициализации с помощью init-method, этот метод также будет вызываться.
- Если компоненты реализуют интерфейс BeanPostProcessor, Spring вызовет их метод postProcessAfterInitialization().
- На этом этапе bean-компонент готов к использованию приложением. Они останутся в контексте приложения до тех пор, пока контекст приложения не будет уничтожен.
- Если компонент реализует интерфейс DisposableBean, Spring вызовет его метод интерфейса destroy() Аналогичным образом, если компонент объявляет метод уничтожения с помощью метода destroy, этот метод также будет вызываться.
Это основной интерфейс и жизненный цикл Bean in Spring, этого достаточно, чтобы ответить на описанный выше процесс в интервью. Однако, просматривая документацию JavaDoc, я обнаружил, что помимо вышеперечисленных интерфейсов в процессе инициализации задействованы и другие интерфейсы:
Выдержка из org.springframework.beans.factory.BeanFactory, все связанные интерфейсы следующие, существующие не нужно помечать, а дополнительные связанные интерфейсы помечены ниже
Полный жизненный цикл фасоли
Текст поясняется следующим образом:
------------инициализация------------
- BeanNameAware.setBeanName() устанавливает имя компонента в фабрике компонентов, создавшей этот компонент, вызываемой после установки обычных свойств и перед методом InitializinngBean.afterPropertiesSet().
-
BeanClassLoaderAware.setBeanClassLoader()
: вызывается перед InitializingBean.afterPropertiesSet() после установки обычных свойств. - BeanFactoryAware.setBeanFactory() : обратный вызов предоставляет собственную фабрику экземпляров компонента, вызываемую после установки обычных свойств и перед InitializingBean.afterPropertiesSet() или пользовательскими методами инициализации.
-
EnvironmentAware.setEnvironment()
: установить среду, которая будет вызываться при использовании компонента. -
EmbeddedValueResolverAware.setEmbeddedValueResolver()
: Установите StringValueResolver для решения проблем со встроенным диапазоном значений. -
ResourceLoaderAware.setResourceLoader()
: Вызывается после обычного объекта bean, до afterPropertiesSet или пользовательского метода инициализации, до ApplicationContextAware. -
ApplicationEventPublisherAware.setApplicationEventPublisher()
: Вызывается после обычных свойств bean-компонента, перед инициализацией вызывает afterPropertiesSet или пользовательские методы инициализации. Вызывается перед ApplicationContextAware. -
MessageSourceAware.setMessageSource()
: Вызывается после обычных свойств компонента, перед вызовами инициализации afterPropertiesSet или пользовательских методов инициализации, перед ApplicationContextAware. - ApplicationContextAware.setApplicationContext(): вызывается после создания обычного объекта Bean, перед InitializingBean.afterPropertiesSet или перед определяемым пользователем методом инициализации. Вызывается после ResourceLoaderAware.setResourceLoader, ApplicationEventPublisherAware.setApplicationEventPublisher, MessageSourceAware.
-
ServletContextAware.setServletContext()
: Установить ServletContext во время выполнения, вызывается после обычной инициализации компонента, вызывается перед InitializingBean.afterPropertiesSet, вызывается после ApplicationContextAware.Примечание: когда WebApplicationContext работает - BeanPostProcessor.postProcessBeforeInitialization() : примените этот BeanPostProcessor к заданному новому экземпляру компонента Вызывается перед любыми методами обратного вызова инициализации компонента (например, InitializingBean.afterPropertiesSet или пользовательскими методами инициализации). Этот bean-компонент будет готов для заполнения значения свойства. Возвращенный экземпляр bean-компонента может быть обернут простым объектом, а реализация по умолчанию возвращает bean-компонент.
- BeanPostProcessor.postProcessAfterInitialization() : примените этот BeanPostProcessor к данному новому экземпляру компонента. Вызывается после любых методов обратного вызова инициализации компонента (например, InitializingBean.afterPropertiesSet или пользовательских методов инициализации). Этот bean-компонент будет готов для заполнения значения свойства. Возвращенный экземпляр компонента может быть обернут простым объектом.
- InitializingBean.afterPropertiesSet(): вызывается BeanFactory после установки всех свойств bean-компонента (и удовлетворения требований BeanFactory и ApplicationContextAware).
------------разрушать------------
Когда BeanFactory закрывается, жизненный цикл Bean вызывает следующие методы:
-
DestructionAwareBeanPostProcessor.postProcessBeforeDestruction()
: применяет этот BeanPostProcessor к данному экземпляру компонента перед его уничтожением. Возможность вызывать пользовательские обратные вызовы, такие как методы уничтожения и уничтожения DisposableBean, этот обратный вызов применяется только к одноэлементным компонентам на фабрике (включая внутренние компоненты) - Реализован собственный метод destroy()
2. Проверка жизненного цикла бина
Для того, чтобы проверить процесс жизненного цикла Бина, есть две формы: одна подготовлена для интервью, а другая подготовлена для понимания всего процесса.Давайте посмотрим на код ниже:
- Book.class
public class Book implements BeanNameAware,BeanFactoryAware,
ApplicationContextAware,InitializingBean,DisposableBean {
private String bookName;
public Book(){
System.out.println("Book Initializing ");
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("Book.setBeanFactory invoke");
}
public void setBeanName(String name) {
System.out.println("Book.setBeanName invoke");
}
public void destroy() throws Exception {
System.out.println("Book.destory invoke");
}
public void afterPropertiesSet() throws Exception {
System.out.println("Book.afterPropertiesSet invoke");
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("Book.setApplicationContext invoke");
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
System.out.println("setBookName: Book name has set.");
}
public void myPostConstruct(){
System.out.println("Book.myPostConstruct invoke");
}
// 自定义初始化方法
@PostConstruct
public void springPostConstruct(){
System.out.println("@PostConstruct");
}
public void myPreDestory(){
System.out.println("Book.myPreDestory invoke");
System.out.println("---------------destroy-----------------");
}
// 自定义销毁方法
@PreDestroy
public void springPreDestory(){
System.out.println("@PreDestory");
}
@Override
protected void finalize() throws Throwable {
System.out.println("------inside finalize-----");
}
}
- Настройте MyBeanPostProcessor, реализующий BeanPostProcessor:
public class MyBeanPostProcessor implements BeanPostProcessor {
// 容器加载的时候会加载一些其他的bean,会调用初始化前和初始化后方法
// 这次只关注book(bean)的生命周期
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof Book){
System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization");
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof Book){
System.out.println("MyBeanPostProcessor.postProcessAfterInitialization");
}
return bean;
}
}
- Создайте новый Bean-Lifecycle.xml в каталоге ресурсов.
<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-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描bean -->
<context:component-scan base-package="com.bean.lifecycle"/>
<!-- 实现了用户自定义初始化和销毁方法 -->
<bean id="book" class="com.bean.lifecycle.Book" init-method="myPostConstruct" destroy-method="myPreDestory">
<!-- 注入bean 属性名称 -->
<property name="bookName" value="thingking in java" />
</bean>
<!--引入自定义的BeanPostProcessor-->
<bean class="com.bean.lifecycle.MyBeanPostProcessor"/>
</beans>
- Сделайте тест класса Startup и создайте новое SpringBeanLifecyClipplication
public class SpringBeanLifecycleApplication {
public static void main(String[] args) throws InterruptedException {
// 为面试而准备的Bean生命周期加载过程
ApplicationContext context = new ClassPathXmlApplicationContext("Bean-Lifecycle.xml");
Book book = (Book)context.getBean("book");
System.out.println("Book name = " + book.getBookName());
((ClassPathXmlApplicationContext) context).destroy();
}
}
Запустите тест, и вывод будет следующим:
Book Initializing setBookName: Book name has set. Book.setBeanName invoke Book.setBeanFactory invoke Book.setApplicationContext invoke MyBeanPostProcessor.postProcessBeforeInitialization @PostConstruct Book.afterPropertiesSet invoke Book.myPostConstruct invoke MyBeanPostProcessor.postProcessAfterInitialization Book name = thingking in java
@PreDestory Book.destory invoke Book.myPreDestory invoke ---------------destroy-----------------
- Чтобы проверить полный жизненный цикл Bean, необходимо создать новый SubBookClass для наследования класса Book.
public class SubBookClass extends Book implements BeanClassLoaderAware,
EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,
ApplicationEventPublisherAware,MessageSourceAware{
private String bookSystem;
public String getBookSystem() {
return bookSystem;
}
public void setBookSystem(String bookSystem) {
System.out.println("设置BookSystem 的属性值");
this.bookSystem = bookSystem;
}
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("SubBookClass.setBeanClassLoader() 方法被调用了");
}
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
System.out.println("SubBookClass.setApplicationEventPublisher() 方法被调用了");
}
public void setEmbeddedValueResolver(StringValueResolver resolver) {
System.out.println("SubBookClass.setEmbeddedValueResolver() 方法被调用了");
}
public void setEnvironment(Environment environment) {
System.out.println("SubBookClass.setEnvironment() 方法被调用了");
}
public void setMessageSource(MessageSource messageSource) {
System.out.println("SubBookClass.setMessageSource() 方法被调用了");
}
public void setResourceLoader(ResourceLoader resourceLoader) {
System.out.println("SubBookClass.setResourceLoader() 方法被调用了");
}
}
Приведенный выше класс SubBookClass с книгой
互补
связь.
- Создайте новый SubBean-Lifecycle.xml и внедрите SubBookClass.
<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-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="bookClass" class="com.bean.lifecycle.SubBookClass" init-method="myPostConstruct" destroy-method="myPreDestory">
<property name="bookSystem" value="Java System" />
</bean>
<bean class="com.bean.lifecycle.MyBeanPostProcessor"/>
</beans>
- Полное приложение SpringBeanLifecycleApplication выглядит следующим образом:
public class SpringBeanLifecycleApplication {
public static void main(String[] args) throws InterruptedException {
// 为面试而准备的Bean生命周期加载过程
ApplicationContext context = new ClassPathXmlApplicationContext("Bean-Lifecycle.xml");
Book book = (Book)context.getBean("book");
System.out.println("Book name = " + book.getBookName());
((ClassPathXmlApplicationContext) context).destroy();
// 完整的加载过程,当然了解的越多越好
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("SubBean-Lifecycle.xml");
SubBookClass subBookClass = (SubBookClass) applicationContext.getBean("bookClass");
System.out.println("BookSystemName = " + subBookClass.getBookSystem());
((ClassPathXmlApplicationContext) applicationContext).registerShutdownHook();
}
}
Выведите полный результат:
Book Initializing setBookName: Book name has set. Book.setBeanName invoke Book.setBeanFactory invoke Book.setApplicationContext invoke MyBeanPostProcessor.postProcessBeforeInitialization @PostConstruct Book.afterPropertiesSet invoke Book.myPostConstruct invoke MyBeanPostProcessor.postProcessAfterInitialization Book name = thingking in java @PreDestory Book.destory invoke Book.myPreDestory invoke ---------------destroy-----------------
Инициализация книги Установите значение свойства BookSystem Book.setBeanName вызывает Вызывается метод SubBookClass.setBeanClassLoader(). Вызов Book.setBeanFactory Метод SubBookClass.setEnvironment() вызывается Вызывается метод SubBookClass.setEmbeddedValueResolver() Вызывается метод SubBookClass.setResourceLoader() Вызывается метод SubBookClass.setApplicationEventPublisher() Вызывается метод SubBookClass.setMessageSource() Book.setApplicationContext вызывает MyBeanPostProcessor.postProcessBeforeInitialization Book.afterPropertiesSet вызывает Вызов Book.myPostConstruct MyBeanPostProcessor.postProcessAfterInitialization BookSystemName = Система Java Book.destory вызывает Вызов Book.myPreDestory ---------------разрушать-----------------
Постскриптум: Эта статья - вывод, который я получил, читая различные книги и искал информацию в Интернете, в том числе на некоторых зарубежных сайтах, и записал ее, но не нашел.Жизненный цикл Spring Bean (очень подробный)В этой статье приветствуются класс InstantiationAwareBeanPostProcessorAdapter и интерфейсный метод фабричного постпроцессора.Спасибо.
Кроме того, добавьте мой WeChat becxuan, присоединяйтесь к группе ежедневных вопросов и делитесь одним вопросом для интервью каждый день.Для получения дополнительной информации, пожалуйста, обратитесь к моему Github,Будь лучшим лучшимJavaer
Я сам переписал шесть PDF-файлов. После того, как WeChat искал «Programmer cxuan» и следил за официальной учетной записью, я ответил cxuan в фоновом режиме и получил все PDF-файлы.Эти PDF-файлы следующие: