文章目录
- 前言
- 需求分析
- 思路分析
-
- 设计解析
- 类图
- 项目结构
- 相关代码
- BeanFactoryPostProcessor(bean工厂扩展)
- BeanPostProcessor(bean扩展)
- ApplicationContext (上下文行为定义,继承ListableBeanFactory,从而可以根据类类型获取前后置处理器)
- ConfigurableApplicationContext(上下文行为定义)
- AbstractApplicationContext(上下文行为规范,使用模板方法定义执行顺序)
- AbstractRefreshableApplicationContext(上下文刷新行为抽象,单一职责最好的体现)
- AbstractXmlApplicationContext (上下文加载bean抽象,实现自己的职责:加载xml文件并注册bean定义)
- 具体实现
- 测试
- 参考文献
前言
在上一章我们完成的容器初始化,从而完成bean定义注册和bean对象的初始化。
在日常开发中,我们会遇到这样的问题,加入我们需要修改某个bean对象的成员属性,假如只有需要修改的bean对象还好说,我们可以通过xml配置修改来解决问题,但是若遇到一个依赖关系十分复杂且不止一个bean对象,我们又该怎么办呢?
需求分析
所以我们需要一个实现一个功能可以在容器初始化的时候修改bean定义信息完成所有bean定义的修改操作,或者在实例化bean前后修改bean的相关属性。同时我们还希望这个扩展可以对用户友好,说白了,就是我们需要修改某个bean属性的时候操作尽可能简单。
思路分析
设计解析
如下图所示,我们需要编写一个容器上下文,通过集成现有bean容器,并封装一个refresh方法来实现bean加载、注册、扩展、实例化四个操作。
类图
架构设计如下图所示,笔者还是延续了之前的设计思想使用接口定义动作,抽象类实现模板方法以及根据单一职责原则实现自己应该有的类,再有子类实现具体实现细节
项目结构
使用命令即可导入到xx.txt目录
tree /f >xx.txt
├─src
│ ├─main
│ │ ├─java
│ │ │ └─cn
│ │ │ └─shark
│ │ │ └─springframework
│ │ │ ├─beans
│ │ │ │ │ BeansException.java
│ │ │ │ │ PropertyValue.java
│ │ │ │ │ PropertyValues.java
│ │ │ │ │
│ │ │ │ └─factory
│ │ │ │ │ BeanFactory.java
│ │ │ │ │ ConfigurableListableBeanFactory.java
│ │ │ │ │ HierarchicalBeanFactory.java
│ │ │ │ │ ListableBeanFactory.java
│ │ │ │ │
│ │ │ │ ├─config
│ │ │ │ │ AutowireCapableBeanFactory.java
│ │ │ │ │ BeanDefinition.java
│ │ │ │ │ BeanFactoryPostProcessor.java
│ │ │ │ │ BeanPostProcessor.java
│ │ │ │ │ BeanReference.java
│ │ │ │ │ ConfigurableBeanFactory.java
│ │ │ │ │ SingletonBeanRegistry.java
│ │ │ │ │
│ │ │ │ ├─core
│ │ │ │ │ └─io
│ │ │ │ │ ClassPathResource.java
│ │ │ │ │ DefaultResourceLoader.java
│ │ │ │ │ FileSystemResource.java
│ │ │ │ │ Resource.java
│ │ │ │ │ ResourceLoader.java
│ │ │ │ │ UrlResource.java
│ │ │ │ │
│ │ │ │ ├─support
│ │ │ │ │ AbstractAutowireCapableBeanFactory.java
│ │ │ │ │ AbstractBeanDefinitionReader.java
│ │ │ │ │ AbstractBeanFactory.java
│ │ │ │ │ BeanDefinitionReader.java
│ │ │ │ │ BeanDefinitionRegistry.java
│ │ │ │ │ CglibSubclassingInstantiationStrategy.java
│ │ │ │ │ DefaultListableBeanFactory.java
│ │ │ │ │ DefaultSingletonBeanRegistry.java
│ │ │ │ │ InstantiationStrategy.java
│ │ │ │ │ SimpleInstantiationStrategy.java
│ │ │ │ │
│ │ │ │ ├─util
│ │ │ │ │ ClassUtils.java
│ │ │ │ │
│ │ │ │ └─xml
│ │ │ │ XmlBeanDefinitionReader.java
│ │ │ │
│ │ │ └─context
│ │ │ │ ApplicationContext.java
│ │ │ │ ConfigurableApplicationContext.java
│ │ │ │
│ │ │ └─support
│ │ │ AbstractApplicationContext.java
│ │ │ AbstractRefreshableApplicationContext.java
│ │ │ AbstractXmlApplicationContext.java
│ │ │ ClassPathXmlApplicationContext.java
│ │ │
│ │ └─resources
│ └─test
│ ├─java
│ │ └─cn
│ │ └─shark
│ │ └─springframework
│ │ │ ApiTest.java
│ │ │
│ │ ├─bean
│ │ │ UserDao.java
│ │ │ UserService.java
│ │ │
│ │ └─common
│ │ MyBeanFactoryPostProcessor.java
│ │ MyBeanPostProcessor.java
│ │
│ └─resources
│ important.properties
│ spring.xml
相关代码
BeanFactoryPostProcessor(bean工厂扩展)
package cn.shark.springframework.beans.factory.config;
import cn.shark.springframework.beans.BeansException;
import cn.shark.springframework.beans.factory.ConfigurableListableBeanFactory;
public interface BeanFactoryPostProcessor {
/**
* 在所有的 BeanDefinition 加载完成后,实例化 Bean 对象之前,提供修改 BeanDefinition 属性的机制
*
* @param beanFactory
* @throws BeansException
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
BeanPostProcessor(bean扩展)
package cn.shark.springframework.beans.factory.config;
import cn.shark.springframework.beans.BeansException;
public interface BeanPostProcessor {
/**
* 在 Bean 对象执行初始化方法之前,执行此方法
*
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
Object postProcessBeforeInitialization(Object bean,String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean,String beanName) throws BeansException;
}
ApplicationContext (上下文行为定义,继承ListableBeanFactory,从而可以根据类类型获取前后置处理器)
该类看没有实现任何东西,但是很好的实现了各个类与spring容器的完美解耦,并且拿到了ListableBeanFactory具备的行为,这样就可以让其子类可根据需要实现根据类类型获取bean的函数。
package cn.shark.springframework.context;
import cn.shark.springframework.beans.factory.ListableBeanFactory;
public interface ApplicationContext extends ListableBeanFactory {
}
ConfigurableApplicationContext(上下文行为定义)
该类继承父类的所有功能,并规范之后所有子类都必须执行的动作,而具体实现交由后者实现。
package cn.shark.springframework.context;
import cn.shark.springframework.beans.BeansException;
public interface ConfigurableApplicationContext extends ApplicationContext {
/**
* 刷新容器
*
* @throws BeansException
*/
void refresh() throws BeansException;
}
AbstractApplicationContext(上下文行为规范,使用模板方法定义执行顺序)
使用模板方法完成其父类(ConfigurableApplicationContext )实现模板,由于bean工厂具体情况未知,所有讲bean工厂刷新和获取作为抽象方法给后者实现
package cn.shark.springframework.context.support;
import cn.shark.springframework.beans.BeansException;
import cn.shark.springframework.beans.factory.ConfigurableListableBeanFactory;
import cn.shark.springframework.beans.factory.config.BeanFactoryPostProcessor;
import cn.shark.springframework.beans.factory.config.BeanPostProcessor;
import cn.shark.springframework.beans.factory.config.ConfigurableBeanFactory;
import cn.shark.springframework.beans.factory.core.io.DefaultResourceLoader;
import cn.shark.springframework.context.ConfigurableApplicationContext;
import java.util.Map;
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
/**
* 刷新容器
*
* @throws BeansException
*/
@Override
public void refresh() throws BeansException {
// 1. 创建 BeanFactory,并加载 BeanDefinition
refreshBeanFactory();
// 2. 获取 BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 3. 在 Bean 实例化之前,执行 BeanFactoryPostProcessor (Invoke factory processors registered as beans in the context.)
invokeBeanFactoryPostProcessors(beanFactory);
// 4. BeanPostProcessor 需要提前于其他 Bean 对象实例化之前执行注册操作
registerBeanPostProcessors(beanFactory);
// 5. 提前实例化单例Bean对象
beanFactory.preInstantiateSingletons();
}
protected abstract void refreshBeanFactory() throws BeansException;
protected abstract ConfigurableListableBeanFactory getBeanFactory();
private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()) {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
}
}
private void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) {
beanFactory.addBeanPostProcessor(beanPostProcessor);
}
}
/**
* 按照类型返回bean实例
*
* @param type
* @return
* @throws BeansException
*/
@Override
public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
return getBeanFactory().getBeansOfType(type);
}
/**
* 返回注册表中所有的bean名称
*
* @return
*/
@Override
public String[] getBeanDefinitionNames() {
return getBeanFactory().getBeanDefinitionNames();
}
@Override
public Object getBean(String name) throws BeansException {
return getBeanFactory().getBean(name);
}
@Override
public Object getBean(String name, Object... agrs) throws BeansException {
return getBeanFactory().getBean(name,agrs);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return getBeanFactory().getBean(name,requiredType);
}
}
AbstractRefreshableApplicationContext(上下文刷新行为抽象,单一职责最好的体现)
package cn.shark.springframework.context.support;
import cn.shark.springframework.beans.BeansException;
import cn.shark.springframework.beans.factory.ConfigurableListableBeanFactory;
import cn.shark.springframework.beans.factory.support.DefaultListableBeanFactory;
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
private DefaultListableBeanFactory beanFactory;
@Override
protected void refreshBeanFactory() throws BeansException {
DefaultListableBeanFactory beanFactory = createBeanFactory();
loadBeanDefinitions(beanFactory);;
this.beanFactory=beanFactory;
}
private DefaultListableBeanFactory createBeanFactory(){
return new DefaultListableBeanFactory();
}
protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException;
@Override
protected ConfigurableListableBeanFactory getBeanFactory() {
return beanFactory;
}
}
AbstractXmlApplicationContext (上下文加载bean抽象,实现自己的职责:加载xml文件并注册bean定义)
package cn.shark.springframework.context.support;
import cn.shark.springframework.beans.BeansException;
import cn.shark.springframework.beans.factory.support.DefaultListableBeanFactory;
import cn.shark.springframework.beans.factory.xml.XmlBeanDefinitionReader;
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext {
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException {
XmlBeanDefinitionReader beanDefinitionReader=new XmlBeanDefinitionReader(beanFactory,this);
String[] configLocations = getConfigLocations();
if (null!=configLocations){
beanDefinitionReader.loadBeanDefinitions(configLocations);
}
}
protected abstract String[] getConfigLocations();
}
具体实现
package cn.shark.springframework.context.support;
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
private String[] configLocations;
public ClassPathXmlApplicationContext() {
}
public ClassPathXmlApplicationContext(String configLocations) {
this(new String[]{
configLocations});
}
public ClassPathXmlApplicationContext(String[] configLocations) {
this.configLocations = configLocations;
refresh();
}
@Override
protected String[] getConfigLocations() {
return configLocations;
}
}
测试
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="userDao" class="cn.shark.springframework.bean.UserDao"/>
<bean id="userService" class="cn.shark.springframework.bean.UserService">
<property name="uId" value="10001"/>
<property name="company" value="腾讯"/>
<property name="location" value="深圳"/>
<property name="userDao" ref="userDao"/>
</bean>
<bean class="cn.shark.springframework.common.MyBeanFactoryPostProcessor"/>
<bean class="cn.shark.springframework.common.MyBeanPostProcessor"/>
</beans>
测试代码
UserDao
package cn.shark.springframework.bean;
import java.util.HashMap;
import java.util.Map;
public class UserDao {
private static Map<String, String> hashMap = new HashMap<>();
static {
hashMap.put("10001", "巨大情");
hashMap.put("10002", "巨二情");
hashMap.put("10003", "巨三情");
}
public String queryUserName(String uId) {
return hashMap.get(uId);
}
}
UserService
package cn.shark.springframework.bean;
/**
* 测试bean
*
* @author Zsy
* @date 2021-08-30 21:41
*/
public class UserService {
private String uId;
private String company;
private String location;
private UserDao userDao;
public String queryUserInfo() {
return userDao.queryUserName(uId) + "," + company + "," + location;
}
public String getuId() {
return uId;
}
public void setuId(String uId) {
this.uId = uId;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
MyBeanFactoryPostProcessor
package cn.shark.springframework.common;
import cn.shark.springframework.beans.BeansException;
import cn.shark.springframework.beans.PropertyValue;
import cn.shark.springframework.beans.PropertyValues;
import cn.shark.springframework.beans.factory.ConfigurableListableBeanFactory;
import cn.shark.springframework.beans.factory.config.BeanDefinition;
import cn.shark.springframework.beans.factory.config.BeanFactoryPostProcessor;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
/**
* 在所有的 BeanDefinition 加载完成后,实例化 Bean 对象之前,提供修改 BeanDefinition 属性的机制
*
* @param beanFactory
* @throws BeansException
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
PropertyValues propertyValues=beanDefinition.getPropertyValues();
propertyValues.addPropertyValue(new PropertyValue("company","改为:测试公司"));
}
}
MyBeanPostProcessor
package cn.shark.springframework.common;
import cn.shark.springframework.bean.UserService;
import cn.shark.springframework.beans.BeansException;
import cn.shark.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {
/**
* 在 Bean 对象执行初始化方法之前,执行此方法
*
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)){
UserService userService= (UserService) bean;
userService.setLocation("改为:福建省");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
测试代码
@Test
public void test_Processor(){
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:spring.xml");
UserService userService = applicationContext.getBean("userService", UserService.class);
String result = userService.queryUserInfo();
System.out.println(result);
}
结果
巨大情,改为:测试公司,改为:福建省