继续完善 Spring Bean 容器框架的功能开发
1、bean的创建交给容器
2、getBean采用模板方法设计模式,指定调用过程和标准定义,控制了后续的实现者不用关心调用逻辑,按照统一方式执行
3、容器框架的类结构优化,方便后续功能的扩展
├─src
│ ├─main
│ │ ├─java
│ │ │ └─cn
│ │ │ └─ljc
│ │ │ └─springframework
│ │ │ └─beans
│ │ │ │ BeansException.java
│ │ │ │
│ │ │ └─factory
│ │ │ │ BeanFactory.java
│ │ │ │
│ │ │ ├─config
│ │ │ │ BeanDefinition.java
│ │ │ │ SingletonBeanRegistry.java
│ │ │ │
│ │ │ └─support
│ │ │ AbstractAutowireCapableBeanFactory.java
│ │ │ AbstractBeanFactory.java
│ │ │ BeanDefinitionRegistry.java
│ │ │ DefaultListableBeanFactory.java
│ │ │ DefaultSingletonBeanRegistry.java
│ │ │
│ │ └─resources
│ └─test
│ └─java
│ └─springframework
│ └─test
│ │ ApiTest.java
│ │
│ └─bean
│ UserService.java

/*** @desc Bean工厂* @Author: ljc* @Date: 2022/11/28 10:36*/
public interface BeanFactory {Object getBean(String name) throws BeansException;}
上一章的BeanFactory 是一个类,这里把他抽象了,变成一个接口,方便扩展
/*** @desc Bean定义* @Author: ljc* @Date: 2022/11/28 10:35*/
public class BeanDefinition {private Class beanClass;public BeanDefinition(Class beanClass) {this.beanClass = beanClass;}public Class getBeanClass() {return beanClass;}public void setBeanClass(Class beanClass) {this.beanClass = beanClass;}
}
上一章Object beanClass 改为Class beanClass,bean的实例化操作可以放到容器中去处理
单例注册bean的接口
/*** @desc 单例注册接口定义* @Author: ljc* @Date: 2022/11/30 17:27*/
public interface SingletonBeanRegistry {Object getSingleton(String beanName);}
提供了一个获取单例bean的接口
单例注册bean的实现
/*** @desc 单例注册接口的实现类* @Author: ljc* @Date: 2022/11/30 17:28*/
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {/*** @desc: 单例池* @author: ljc* @date: 2022/12/7 10:57* @param:* @return:**/private Map singletonObjects = new HashMap<>();/*** @desc: 获取单例bean* @author: ljc* @date: 2022/12/7 10:57* @param: [beanName]* @return: java.lang.Object**/@Overridepublic Object getSingleton(String beanName) {return singletonObjects.get(beanName);}/*** @desc: 入单例池* @author: ljc* @date: 2022/12/7 10:56* @param: [beanName, singletonObject]* @return: void**/protected void addSingleton(String beanName,Object singletonObject){singletonObjects.put(beanName,singletonObject);}
}
实现了获取单例bean的接口,并且定义了一个对象单例池,以及提供了添加对象到单例池的保护方法
保证单一职责,只负责处理单例Bean的处理
/*** @desc 抽象bean工厂类* @Author: ljc* @Date: 2022/12/7 11:10*/
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {@Overridepublic Object getBean(String name) throws BeansException {Object bean = getSingleton(name);if (bean != null) {return bean;}BeanDefinition beanDefinition = getBeanDefinition(name);return createBean(name, beanDefinition);}protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;protected abstract Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException;}
新增了2个抽象方法,getBeanDefinition和createBean;
AbstractBeanFactory 继承于DefaultSingletonBeanRegistry,获得了单例注册bean的能力,并且实现了bean工厂的getBean方法
在getBean里面只定义了调用过程(模板模式),并没有自己去实现,让实现此抽象的类去完成。
PS:
这样使用模板模式 (opens new window)的设计方式,可以统一收口通用核心方法的调用逻辑和标准定义,也就很好的控制了后续的实现者不用关心调用逻辑,按照统一方式执行。那么类的继承者只需要关心具体方法的逻辑实现即可
/*** @desc 实例化Bean类* @Author: ljc* @Date: 2022/12/7 13:06*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory{@Overrideprotected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {Object bean = null;try {bean = beanDefinition.getBeanClass().newInstance();} catch (InstantiationException | IllegalAccessException e) {throw new BeansException("Instantiation of bean failed", e);}addSingleton(beanName,bean);return bean;}
}
AbstractAutowireCapableBeanFactory 本身也是一个抽象类
它只会实现属于自己的抽象方法,其他抽象方法由继承AbstractAutowireCapableBeanFactory 的类实现。
这里会有一个问题,如果是带参数的构造方法如何处理?(在源码里,其实是有一个寻找构造方法的判断处理)
/*** @desc bena工厂核心实现类* @Author: ljc* @Date: 2022/12/7 13:33*/
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry{// bean定义的缓存private final Map beanDefinitionMap = new HashMap<>();@Overrideprotected BeanDefinition getBeanDefinition(String beanName) throws BeansException {BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);if(beanDefinition ==null) throw new BeansException("No bean named " + beanName + " is defined");return beanDefinition;}@Overridepublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeansException {beanDefinitionMap.put(beanName, beanDefinition);}
}
继承于AbstractAutowireCapableBeanFactory ,拥有了创建bean、获取bean的能力
并且实现了BeanDefinitionRegistry接口的,内部实现了egisterBeanDefinition(实现了Bean定义)
/*** @desc 用户服务类* @Author: ljc* @Date: 2022/11/28 10:56*/
public class UserService {public void queryUserInfo(){System.out.println("查询用户信息");}}
/*** @desc 测试* @Author: ljc* @Date: 2022/11/28 10:57*/
public class ApiTest {@Testpublic void test_BeanFactory() {// 1.初始化 BeanFactoryDefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();// 2.注册 beanBeanDefinition beanDefinition = new BeanDefinition(UserService.class);beanFactory.registerBeanDefinition("userService", beanDefinition);// 3.第一次获取 beanUserService userService = (UserService) beanFactory.getBean("userService");userService.queryUserInfo();// 4.第二次获取 bean from SingletonUserService userService_singleton = (UserService) beanFactory.getBean("userService");userService_singleton.queryUserInfo();System.out.println(userService);System.out.println(userService_singleton);}}
测试案例主要包含了 初始化bean工厂、注册bean、获取bean。
上一章的测试用例,可以看到是通过new userService()来定义bean,现在是把UserService的class传给bean定义。
调用2次获取bean,主要是用于测试第二次获取时,是否从缓存里获取,按上述代码,结果是肯定的!
查询用户信息
查询用户信息
springframework.test.bean.UserService@504bae78
springframework.test.bean.UserService@504bae78Process finished with exit code 0
可以看到打印的对象是同一个
可以看到本章节,增加了很多类和接口,为什么要设计成这样?
基于接口、抽象编程,便于扩展
松耦合,让每个类只承担自己职责的那部分,尽可能保证单一职责