一、Spring:BeanPosPrecessor简介:
Bean后处理器用来对bean的功能进行扩展增强,对IoC容器中的所有bean都有效。BeanPosProcessor后置处理器执行的时机为:在Bean实例化且装配数据后,在执行初始化前后,生命周期如图所示:
二、实现步骤
- 定义一个类,实现BeanPostProcessor接口
- 将该后处理器添加到IoC容器中
三、代码实现:
此实例为:自定义一个用户类,用户的属性为字符串数据类型,在IOC容器实例化后,给此Bean装配数据,装配数据后的Bean,通过后置处理器BeanPosProcessor,将此Bean传入到处理器中,利用正则表达式,解析Bean中的属性值,得到解析后的字符串,再从properties文件中得到对应的数据值,重新给Bean的属性赋值,经过后置处理器处理过的Bean,与在配置文件xml中装配的值是不一样的,属性的值来自于properties文件。具体代码如下:
(一)自定义Bean
定义两个Bean,这两个Bean装配数据后,都会通过BeanPosProcessor后置处理器对Bean的属性进行修改处理。
1.Bean
// TODO: 2021/6/22 自定义Bean,此Bean有用户名和用户年龄两人个属性
public class UserIoc3 {
private String name;
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "UserIoc3{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
2.Bean
public class UserIoc31 {
private String salary;
private String email;
public String getSalary() {
return salary;
}
public void setSalary(String salary) {
this.salary = salary;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "UserIoc31{" +
"salary='" + salary + '\'' +
", email='" + email + '\'' +
'}';
}
}
(二)自定义BeanPosProcessor后置处理器
此后置处理器实现以下功能:一是对Bean中的属性值进行解析,得到解析后的字符串;二是调用properties文件,将其装入Properites对象中;三是从Properties对象中读取解析后字符串对应属性值;四是将读取出来的属性值重新装入到Bean中。
public class UserIoc3BeanPosProcess implements BeanPostProcessor {
private Resource resource;
public Resource getResource() {
return resource;
}
public void setResource(Resource resource) {
this.resource = resource;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Class<?> aClass = bean.getClass();
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
Class<?> type = declaredField.getType();
if (type == String.class) {
try {
declaredField.setAccessible(true);
String o = (String) declaredField.get(bean);
String str_resolver = getResolver(o);
declaredField.set(bean, str_resolver);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} else {
throw new RuntimeException("不支持的类型!");
}
}
return bean;
}
private String getResolver(String o) {
Pattern compile = Pattern.compile("\\$\\{(.*)\\}");
Matcher matcher = compile.matcher(o);
if (matcher.matches()) {
String group = matcher.group(1);
return getPropertiesName(group);
}
return o;
}
private String getPropertiesName(String group) {
Properties properties = new Properties();
try {
InputStream inputStream = resource.getInputStream();
properties.load(inputStream);
if (properties.containsKey(group)) {
String property = properties.getProperty(group);
return property;
} else {
throw new RuntimeException("没有找到相对应的");
}
} catch (IOException e) {
e.printStackTrace();
}
return group;
}
}
(三)设置配置文件(*.xml)
设置配置文件,分别将两个自定义Bean 和 BeanPosProcessor后置处理器加载到配置文件中。通过IOC容器调用配置文件,生成Bean实例。
xml文件
<bean id="userioc3" class="ioc3.UserIoc3">
<property name="name" value="${name}"/>
<property name="age" value="${age}"/>
</bean>
<bean id="userioc31" class="ioc3.UserIoc31">
<property name="salary" value="${salary}"/>
<property name="email" value="${email}"/>
</bean>
<bean class="ioc3.UserIoc3BeanPosProcess">
<property name="resource" value="classpath:ioc3/ioc3.properties"/>
</bean>
properties文件
name=javahello
age=20
email=weijun1227
salary=9000
(四)生成IOC容器,得到被后置处理器处理过的Bean
@Test
public void test73() {
ApplicationContext ac = new ClassPathXmlApplicationContext("ioc3/ioc3.xml");
UserIoc3 userioc3 = (UserIoc3) ac.getBean("userioc3");
UserIoc31 userioc31 = (UserIoc31) ac.getBean("userioc31");
System.out.println(userioc3);
System.out.println(userioc31);
}