一、项目案例代码:
1.1.Student:
package com;
public class Student {
private String stuName, sex;
public Student() {
System.out.println("1.【Student类的无参构造方法】: 创建学生对象的时候执行。 作用: 对对象进行初始化操作。");
}
public void setStuName(String stuName) {
System.out.println("2.【setName()自定义方法】: 用set方式给属性赋值并在构造方法之后执行。 作用:注入学生的name属性");
this.stuName = stuName;
}
// 自己编写的初始化方法
public void myInit() {
System.out.println("6.【init-method属性设置的方法myInit()】: 一个bean实例化完后(全部属性设置完之后)执行。 " +
"作用: 对对象进行初始化");
}
// 自己编写的销毁方法(和上边的方法相同)
public void myDestroy() {
System.out.println("7.【destroy-method属性设置的方法myDestroy()】: 容器关闭的时候执行, " +
"在销毁bean对象之前执行此方法进行一些操作(比如提示对象即将被销毁)");
}
public void setSex(String sex) {
System.out.println("【set注入】注入学生的sex属性");
this.sex = sex;
}
public String getSex() {
return sex;
}
public String getStuName() {
return stuName;
}
public String toString() {
String msString =
String.format("com.StudentBean{ name=%s,sex=%s }", stuName, sex);
return msString;
}
}
1.2.applicationContext.xml:
<!-- bean标签: 用来配置Student类 (id相当于对象的表示) -->
<!-- 可以通过id获取此配置生成的java对象 -->
<bean id="s1" class="com.Student" scope="singleton" init-method="myInit"
destroy-method="myDestroy">
<property name="stuName" value="yz"/>
</bean>
1.3.Test.java
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
Student s1=ac.getBean(Student.class);
((ClassPathXmlApplicationContext)ac).registerShutdownHook();
}
二、运行结果:
创建bean对象后会调用myInit方法对对象进行初始化。
调用ClassPathXmlApplicationContext对象的registerShutdownHook()方法。
三、重构Student,实现接口:
3.1.重构Student,让其实现三个接口:
让Student类实现生命周期接口BeanNameAware,BeanFactoryAware,InitializingBean并实现对应的方法
public class Student implements BeanNameAware,BeanFactoryAware,InitializingBean{}
//BeanNameAware的setBeanName()方法:如果某个Bean实现了BeanNameAware接口,那么Spring将会将Bean实例的ID传递给setBeanName()方法,
// 在Bean类中新增一个beanName字段,并实现setBeanName()方法。
public void setBeanName(String beanId) {
this.beanName = beanId;
System.out.println("3.【BeanNameAware接口的, setBeanName()方法】: set方法执行完毕之后再执行。 作用:为bean对象设置id值," +
" Bean的id为:" + this.beanName);
}
//BeanFactoryAware的setBeanFactory方法。 beanFactory用于表示spring容器
// (可以理解对象工厂, 所有对象由beanFactory创建且由beanFactory保存)
//在此方法中可以用beanFactory获取其他bean对象来调用(但是spring不推荐,推荐用DI注入的方式)
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
System.out.println("4.【BeanFactoryAware接口的, setBeanFactory()方法】: bean的id设置完后执行。 " +
"作用:可以得到beanFactory对象的引用:"+beanFactory);
//比如:bean对象通过spring容器发布事件
}
//对象的属性设置完毕后,Spring容器会调用InitializingBean接口的afterPropertiesSet方法来对对象一些初始化操作
// (若不需要就不用实现InitializingBean接口)。
public void afterPropertiesSet() throws Exception {
System.out.println("5.【InitializingBean接口的, afterPropertiesSet()方法】 :一个bean实例化完后(全部属性设置完之后)执行。 " +
"作用:来完成一些初始化操作。(和init-method属性属性设置的方法一样)");
}
3.2.运行结果:
-
实例化Bean对象,这个时候Bean的对象是非常低级的,基本不能够被我们使用,因为连最基本的属性都没有设置,可以理解为连Autowired注解都是没有解析的; 我的理解:创建对象并调用构造方法
-
填充属性,当做完这一步,Bean对象基本是完整的了,可以理解为Autowired注解已经解析完毕,依赖注入完成了; 我的理解: 调用set方法已经赋值完毕
-
如果Bean实现了BeanNameAware接口,则调用setBeanName方法, 为bean对象设置id (beanName就是beanId);
-
如果Bean实现了BeanClassLoaderAware接口,则调用setBeanClassLoader方法;
-
如果Bean实现了BeanFactoryAware接口,则调用setBeanFactory方法;用于将Spring容器的引用(beanFactory的引用)传递给bean对象,在此方法中可以通过beanFactory对象来获取Spring容器中的其他Bean对象。(注:BeanClassLoaderAware在案例中没列出,实际BeanClassLoaderAware先执行BeanPostProcessor后执行 );
5.如果Bean实现了InitializingBean接口,调用afterPropertiesSet方法; 一个bean实例化完后(全部属性设置完之后)执行。 作用:来完成一些初始化操作。(和init-method属性属性设置的方法一样)
6.如果Bean定义了init-method方法,则调用Bean的init-method方法。 用于对对象进行初始化;
7.如果应用的上下文被销毁了,并且Bean实现了DisposableBean接口,则调用destroy方法,如果Bean定义了destory-method声明了销毁方法也会被调用(两个作用相同)。
四、BeanPostProcessor接口的实现:
4.1.MyBeanPostProcessor实现BeanPostProcessor接口
package com;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
//BeanPostProcessor的作用域是容器级: 用于对bean对象进行增强(初始化之前和初始化之后)
public class MyBeanPostProcessor implements BeanPostProcessor {
public MyBeanPostProcessor() {
//System.out.println("【BeanPostProcessor接口】调用BeanPostProcessor的构造方法");
}
/**执行时机: bean对象创建了给属性赋值了,但对应的init方法还未执行。
* 作 用 : 给bean对象添加新功能,进行增强(比如替换init方法<就不用写init方法了>)。*/
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor接口:【BeanPostProcessor接口的,postProcessBeforeInitialization方法】init之前执行,作用:对id属性值为 " + beanName + "的对象进行更改(增强)");
return bean;
}
/**执行时机: bean对象创建了给属性赋值了,对应的init方法已经执行完毕。
* 作 用 : 给bean对象添加新功能,进行增强(比如修改bean对象的属性值)。*/
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor接口: 【BeanPostProcessor接口的,postProcessAfterInitialization方法】,init之后执行,作用:对id属性值为 " + beanName + "的对象进行更改(增强)");
return bean;
}
}
4.2.运行结果(其他代码不变):
如果在项目中创建MyBeanPostProcessor 类实现BeanPostProcessor接口,则生命周期方法的运行次序如下:
- 实例化Bean对象,这个时候Bean的对象是非常低级的,基本不能够被我们使用,因为连最基本的属性都没有设置,可以理解为连Autowired注解都是没有解析的; 我的理解:创建对象并调用构造方法
- 填充属性,当做完这一步,Bean对象基本是完整的了,可以理解为Autowired注解已经解析完毕,依赖注入完成了; 我的理解: 调用set方法已经赋值完毕
- 如果Bean实现了BeanNameAware接口,则调用setBeanName方法, 为bean对象设置id (beanName就是beanId);
- 如果Bean实现了BeanClassLoaderAware接口,则调用setBeanClassLoader方法;
- 如果Bean实现了BeanFactoryAware接口,则调用setBeanFactory方法;用于将Spring容器的引用(beanFactory的引用)传递给bean对象,在此方法中可以通过beanFactory对象来获取Spring容器中的其他Bean对象。(注:BeanClassLoaderAware在案例中没列出,实际BeanClassLoaderAware先执行BeanPostProcessor后执行 );
5.调用BeanPostProcessor接口的postProcessBeforeInitialization方法 。init之前执行,作用:对bean对象进行更改(增强)
-
如果Bean实现了InitializingBean接口,调用afterPropertiesSet方法;
-
如果Bean定义了init-method方法,则调用Bean的init-method方法。用于对对象进行初始化;
-
调用BeanPostProcessor的postProcessAfterInitialization方法:当进行到这一步,Bean已经被准备就绪了,一直停留在应用的上下文中,直到被销毁;
9.如果应用的上下文被销毁了,如果Bean实现了DisposableBean接口,则调用destroy方法,如果Bean定义了destory-method声明了销毁方法也会被调用。
五、InstantiationAwareBeanPostProcessor的实现:
5.1.MyInstantiationAwareBeanPostProcessor类实现接口
注: 这里根据课本采用的是InstantiationAwareBeanPostProcessor接口的实现类InstantiationAwareBeanPostProcessorAdapter(书上说为了编程方便)
package com;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
//读音: Instantiation--印思旦欸深 。 单词意思: 实例化
//读音: Processor-----Pro 赛 思儿 。 单词意思: 处理器/加工器
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("【InstantiationAwareBeanPostProcessor接口】 实例化Bean之前调用。");
return null;
}
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("【InstantiationAwareBeanPostProcessor接口】 实例化Bean之后调用。");
return true;
}
}
5.2.applicationContext.xml
<bean id="miabpp" class="com.MyInstantiationAwareBeanPostProcessor"></bean>
5.3.运行结果:
【InstantiationAwareBeanPostProcessor接口】 实例化Bean之前(创建Bean对象之前)调用。
1.【Student类的无参构造方法】: 创建学生对象的时候执行。 作用: 对对象进行初始化操作。
【InstantiationAwareBeanPostProcessor接口】 实例化Bean之后(创建Bean对象之后)调用。
2.【setName()自定义方法】: 用set方式给属性赋值并在构造方法之后执行。 作用:注入学生的name属性
【set注入】注入学生的sex属性
3.【BeanNameAware接口的, setBeanName()方法】: set方法执行完毕之后再执行。 作用:为bean对象设置id值, Bean的id为:s1
4.【BeanFactoryAware接口的, setBeanFactory()方法】: bean的id设置完后执行。 作用:可以得到beanFactory对象的引用:org.springframework.beans.factory.support.DefaultListableBeanFactory@5ebec15: defining beans [beanPostProcessor,s1,beanFactoryPostProcessor,miabpp]; root of factory hierarchy
MyBeanPostProcessor接口:【BeanPostProcessor接口的,postProcessBeforeInitialization方法】init之前执行,作用:对id属性值为 s1的对象进行更改(增强)
5.【InitializingBean接口的, afterPropertiesSet()方法】 :一个bean实例化完后(全部属性设置完之后)执行。 作用:来完成一些初始化操作。(和init-method属性属性设置的方法一样)
6.【init-method属性设置的方法myInit()】: 一个bean实例化完后(全部属性设置完之后)执行。 作用: 对对象进行初始化
MyBeanPostProcessor接口: 【BeanPostProcessor接口的,postProcessAfterInitialization方法】,init之后执行,作用:对id属性值为 s1的对象进行更改(增强)
7.【destroy-method属性设置的方法myDestroy()】: 容器关闭的时候执行, 在销毁bean对象之前执行此方法进行一些操作(比如提示对象即将被销毁)
六、MyBeanFactoryPostProcessor接口的实现:
6.1.MyBeanFactoryPostProcessor实现BeanFactoryPostProcessor接口
package com;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionVisitor;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.util.StringValueResolver;
import java.util.Set;
/**BeanPostProcessor的作用域是容器级: 用于对bean对象进行增强(初始化之前和初始化之后)*/
//BeanFactoryPostProcessor,可以在spring的bean创建之前,修改bean的定义属性。
//也就是说,Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
//private Set<String> strValues;
/*public MyBeanFactoryPostProcessor(Set<String> strValues) {
this.strValues = strValues;
}*/
/**重写BeanFactoryPostProcessor的postProcessBeanFactory方法, 用于:对beanFactory进行增强。
* (这里举例用beanFactory给bean的属性设置值)*/
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("0.【BeanFactoryPostProcessor接口的postProcessBeanFactory()】 " +
"此方法在对象创建之前执行(bean工厂<beanFactory,也就是spring容器>创建之后),作用:对beanFactory进行增强。" +
"(这里举例用beanFactory给bean的属性设置值)");
BeanDefinition beanDefinition=beanFactory.getBeanDefinition("s1");
beanDefinition.getPropertyValues().addPropertyValue("sex","男");//会调用setSex()方法
/*String [] beanIds=beanFactory.getBeanDefinitionNames();//1.获取所有bean的id
for (String beanId : beanIds ) {
BeanDefinition bean=beanFactory.getBeanDefinition(beanId);//2.用beanFactory根据beanId获取bean对象
// 创建了一个string类型的解析器(作用:如果strVal在applicationContext.xml中存在,就用***代替)
StringValueResolver stringValueResolver=new StringValueResolver() {
public String resolveStringValue(String strVal) {
if(strValues.contains( strVal.toLowerCase())){
return "***";
}else{
return strVal;
}
}
};
//使用上边的解析器创建bean对象访问器BeanDefinitionVisitor
BeanDefinitionVisitor beanDefinitionVisitor=new BeanDefinitionVisitor(stringValueResolver);
//3.用beanDefinitionVisitor的visitBeanDefinition方法访问bean对象(对bean对象进行增强,将对象的敏感字替换为***)
beanDefinitionVisitor.visitBeanDefinition(bean);
}*/
}
}
6.2.运行结果:
通过MyBeanFactoryPostProcessor 的postProcessBeanFactory()方法给bean对象的age属性赋值了 (并且最先执行)。
postProcessBeanFactory()方法 在bean对象在实例化之前被执行,而 BeanPostProcessor 的postProcessBeforeInitialization()方法和postProcessAfterInitialization()方法则是在实例化过程中使用(init之前和之后执行)。
实现MyBeanFactoryPostProcessor 接口,可以在 Spring 创建 bean 之前修改 bean 的定义属性。也就是说,Srping 允许 BeanFactoryPostProcessor 在容器实例化 bean 之前读取配置元数据,并可以根据需要进行修改。例如可以把 bean 的 Scope 从 singleton 改为 prototype ,也可以把 property 的值给修改掉。另外可以同时配置多个 BeanFactoryPostProcessor,并通过 order 属性来控制 BeanFactoryPostProcessor 的执行顺序 ( 在实现 BeanFactoryPostProcessor 时应该考虑实现 Ordered 接口 )。
BeanFactoryPostProcessor 是在 Spring 容器加载了定义 bean 的 XML 文件之后,在 bean 实例化之前执行的。接口方法的入参是 ConfigurrableListableBeanFactory 类型,使用该参数可以获取到相关的 bean 的定义信息。
本段话的原文链接:https://blog.csdn.net/Herishwater/article/details/103864534
0.【BeanFactoryPostProcessor接口的postProcessBeanFactory()】 此方法在对象创建之前执行(bean工厂<beanFactory,也就是spring容器>创建之后),作用:对beanFactory进行增强。(这里举例用beanFactory给bean的age属性设置值)
【InstantiationAwareBeanPostProcessor接口】 实例化Bean之前(创建Bean对象之前)调用。
1.【Student类的无参构造方法】: 创建学生对象的时候执行。 作用: 对对象进行初始化操作。
【InstantiationAwareBeanPostProcessor接口】 实例化Bean之后(创建Bean对象之后)调用。
2.【setName()自定义方法】: 用set方式给属性赋值并在构造方法之后执行。 作用:注入学生的name属性
【set注入】注入学生的sex属性
3.【BeanNameAware接口的, setBeanName()方法】: set方法执行完毕之后再执行。 作用:为bean对象设置id值, Bean的id为:s1
4.【BeanFactoryAware接口的, setBeanFactory()方法】: bean的id设置完后执行。 作用:可以得到beanFactory对象的引用:org.springframework.beans.factory.support.DefaultListableBeanFactory@5ebec15: defining beans [beanPostProcessor,s1,beanFactoryPostProcessor,miabpp]; root of factory hierarchy
MyBeanPostProcessor接口:【BeanPostProcessor接口的,postProcessBeforeInitialization方法】init之前执行,作用:对id属性值为 s1的对象进行更改(增强)
5.【InitializingBean接口的, afterPropertiesSet()方法】 :一个bean实例化完后(全部属性设置完之后)执行。 作用:来完成一些初始化操作。(和init-method属性属性设置的方法一样)
6.【init-method属性设置的方法myInit()】: 一个bean实例化完后(全部属性设置完之后)执行。 作用: 对对象进行初始化
MyBeanPostProcessor接口: 【BeanPostProcessor接口的,postProcessAfterInitialization方法】,init之后执行,作用:对id属性值为 s1的对象进行更改(增强)
7.【destroy-method属性设置的方法myDestroy()】: 容器关闭的时候执行, 在销毁bean对象之前执行此方法进行一些操作(比如提示对象即将被销毁)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗