Жизненный цикл Beans в основной серии Spring
Всем привет, последняя статья из серии Spring дала вам некоторое представление о контейнере Spring, а затем рассказала об инициализации основного контекста WebApplicationContext В этом разделе объясняется жизненный цикл bean-компонентов в контейнере Spring. Лично я считаю этот раздел более практичным, и часто использую эти знания в практической работе для решения очень сложных задач. Ну и старая рутина, структура статьи:
- Жизненный цикл компонента в ApplicationContext
1. Жизненный цикл компонента в ApplicationContext
Сначала сфотографируйте:
Все должны быть ошеломлены, когда увидят эту картину. Не волнуйтесь, я объясню это медленно: от getBean(...) в качестве триггерной точки жизненный цикл Bean контейнера Spring прошел жизненный цикл на рисунке, сначала разделенный на категории:- Три шага зеленой стрелки на рисунке (InstantiationAwareBeanPostProcessor) и два шага розовой стрелки (BeanPostProcessor)Интерфейс жизненного цикла на уровне контейнера, Когда Spring загружает любой Bean-компонент в контейнер, эти интерфейсы будут вызываться несколько раз, как показано на рисунке. Эти два процессора называются "Постпроцессор уровня контейнера", их влияние является глобальным и может затронуть все бобы.
- Интерфейс, обведенный большим красным кружком на рисунке, называется "Постпроцессор заводского уровня", аналогичные интерфейсы включают CustomEditorConfigurer, PropertyPlaceholderConfigurer и т. д.,Этот тип интерфейса вызывается только один раз при инициализации контекста, и его целью является завершение обработки некоторых файлов конфигурации.
- Остальное просто.Он относится к интерфейсу уровня бина, который является эксклюзивным для бина.Когда создается экземпляр каждого бина, он вызывает свой собственный уникальный.
Стоит отметить, что ли «Постпроцессор уровня контейнера"все еще"Постпроцессор заводского уровня", их можно настроить с несколькими (например, двумя BeanPostProcessors), если вы хотите контролировать порядок их вызовов, вы можете реализовать интерфейс org.springframework.core.Ordered. Конечно, он вообще не используется, вообще после класса есть только один процессор.
ключевой акцент! :Последовательность вызова этих интерфейсов не является неизменной, она будет меняться в зависимости от версии Spring.Что вам нужно сделать, так это сохранить то же самое, зная, что вы можете использовать эти интерфейсы для выполнения некоторых операций с атрибутами при инициализации компонента.. Последовательность вызова должна быть протестирована в соответствии с конкретной версией. Я приведу вам пример ниже:
public class Student implements BeanFactoryAware, BeanNameAware,
InitializingBean, DisposableBean,ApplicationContextAware {
private String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryAware......");
}
@Override
public void setBeanName(String s) {
System.out.println("BeanNameAware......");
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean......");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean......");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("ApplicationContextAware......");
}
}
BeanFactoryPostProcessor:
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
super();
System.out.println("这是BeanFactoryPostProcessor实现类构造器!!");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
throws BeansException {
System.out.println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");
BeanDefinition bd = arg0.getBeanDefinition("student");
MutablePropertyValues propertyValues = bd.getPropertyValues();
//配置文件中的信息在加载到Spring中后以BeanDefinition的形式存在.在这里又可以更改BeanDefinition,所以可以理解为更改配置文件里面的内容
// propertyValues.add("zdy","123");
}
}
BeanPostProcessor:
public class MyBeanPostProcessor implements BeanPostProcessor {
public MyBeanPostProcessor() {
super();
System.out.println("这是BeanPostProcessor实现类构造器!!");
}
@Override
public Object postProcessAfterInitialization(Object arg0, String arg1)
throws BeansException {
System.out.println("BeanPostProcessor接口方法After对属性进行更改!");
return arg0;
}
@Override
public Object postProcessBeforeInitialization(Object arg0, String arg1)
throws BeansException {
System.out.println("BeanPostProcessor接口方法Before对属性进行更改!");
return arg0;
}
}
InstantiationAwareBeanPostProcessorAdapter:
public class MyInstantiationAwareBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter {
public MyInstantiationAwareBeanPostProcessor() {
super();
System.out.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");
}
// 接口方法、实例化Bean之前调用
@Override
public Object postProcessBeforeInstantiation(Class beanClass,
String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor调用Before方法");
return null;
}
// 接口方法、实例化Bean之后调用
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor调用Ater方法");
return bean;
}
// 接口方法、设置某个属性时调用
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs,
PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法");
return pvs;
}
}
Затем наш основной метод:
public class App
{
public static void main( String[] args )
{
ApplicationContext ac =new ClassPathXmlApplicationContext("applicationContext.xml");
Student stu = (Student) ac.getBean("student");
stu.setName("wangwu");
}
}
Spring файлы проще всего :(Обратите внимание на добавление всех наших собственных определенных процессоров в контейнер)
<?xml version="1.0" encoding="UTF-8"?>
<beans
<bean id="student" class="com.zdy.Student">
<constructor-arg value="zhangsan"/>
</bean>
<bean id="myBeanFactoryPostProcessor" class="com.zdy.MyBeanFactoryPostProcessor"></bean>
<bean id="myInstantiationAwareBeanPostProcessor" class="com.zdy.MyInstantiationAwareBeanPostProcessor"></bean>
<bean id="myBeanPostProcessor" class="com.zdy.MyBeanPostProcessor"></bean>
</beans>
Затем запустите все сразу и посмотрите результат:
输出为:
这是BeanFactoryPostProcessor实现类构造器!!
BeanFactoryPostProcessor调用postProcessBeanFactory方法
这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!
这是BeanPostProcessor实现类构造器!!
InstantiationAwareBeanPostProcessor调用Before方法
InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法
BeanNameAware......
BeanFactoryAware......
ApplicationContextAware......
BeanPostProcessor接口方法Before对属性进行更改!
InitializingBean......
InstantiationAwareBeanPostProcessor调用Ater方法
BeanPostProcessor接口方法After对属性进行更改!
Ну, собственно, общий процесс закончен, расскажу о жизненном цикле бобов в целом:Для того, чтобы максимально раскрыть пользователям свои внутренние механизмы, Spring добавил множество механизмов в процесс создания bean-компонента, и выставил их через так называемый «процессор» Processor, а дальше процессоры имеют свой порядок , мы Все, что нужно сделать, это определить логику процессора, затем зарегистрировать его в контейнере Springhg, и Spring будет его вызывать. Во-вторых, есть еще один способ позволить нашему Бину реализовывать некоторые интерфейсы (аналогично ApplicationContextAware). Таким образом, на определенном этапе инициализации Бина вызывается метод, определенный интерфейсом, для передачи некоторой информации. Например, ApplicationContextAware помещает ApplicationContext передается нам.
Затем я расскажу вам несколько практических моментов, которые все помнят, когда вам нужно вернуться и посмотреть:
- В приведенной выше блок-схеме жизненного цикла обратите внимание на последовательность вызова, чтобы избежать перезаписи свойств.
- BeanFactoryPostProcessor в основном выполняет некоторые операции, когда Spring только что загрузил файл конфигурации и не успел инициализировать Bean. Например, подделка содержимого, настроенного bean-компонентом в файле конфигурации.
- InstantiationAwareBeanPostProcessorAdapter в принципе бесполезен.После инициализации bean-компонента он вызывается, когда значение свойства не установлено.Как и BeanFactoryPostProcessor, он может подделывать информацию, загружаемую в память файлом конфигурации.
- ApplicationContextAware: Очень полезно, внедрить ApplicationContext в Bean.
- InitializingBean: полезно, вы можете выполнить некоторые операции по настройке после того, как все свойства Bean были изменены.
- BeanPostProcessor: Это бесполезно.Спринг-фреймворк используется люто,типа АОП и динамический прокси.Они тут все делают свое дело. Будет время проанализировать с вами позже.
- Другие методы, такие как init-method и destroy, в основном являются декорациями. . Я мало ей пользовался, и знаю только, что есть такая штука.
Эпилог
Ну с вами поделились жизненным циклом Бина.На самом деле там ничего нет.Все знают что есть такая штука.Когда можно использовать "постпроцессор" для дел,можно вернуться и посмотреть на последовательность. Второй — это интерфейс, реализованный некоторыми bean-компонентами, наиболее часто используемыми являются (ApplicationContextAware и InitializingBean). Существует также BeanPostProcessor, потому что метод этого интерфейса будет передавать сущность Bean как Object. Таким образом, некоторыми свойствами можно манипулировать. На самом деле, по правде говоря, программисты используют меньше. Много использовал внутри рамы. Хорошо, эта статья на самом деле довольно грубая, в основном потому, что не о чем говорить,Закончили, Добрый день!
Я чувствую, что этот вопрос нехороший, позвольте мне дать вам портал. Чувствую, что статья грубее меня, давайте объединим для справки (^_^):