学习 Spring 实现 Bean 的定义、注册、获取
学习文档来自小傅哥,详情可以去原文章了解,这边只是简单记录一下学习体会
《Spring 手撸专栏》第 3 章:初显身手,运用设计模式,实现 Bean 的定义、注册、获取
一、工程结构
类似是这样,我这边稍微有点区别,仅做参考
small-spring-step-02
└── src
├── main
│ └── java
│ └── cn.bugstack.springframework.beans
│ ├── factory
│ │ ├── config
│ │ │ ├── BeanDefinition.java
│ │ │ └── SingletonBeanRegistry.java
│ │ ├── support
│ │ │ ├── AbstractAutowireCapableBeanFactory.java
│ │ │ ├── AbstractBeanFactory.java
│ │ │ ├── BeanDefinitionRegistry.java
│ │ │ ├── DefaultListableBeanFactory.java
│ │ │ └── DefaultSingletonBeanRegistry.java
│ │ └── BeanFactory.java
│ └── BeansException.java
└── test
└── java
└── cn.bugstack.springframework.test
├── bean
│ └── UserService.java
└── ApiTest.java
我这边先把主要代码的结构放出来,可以参考,在idea按CTRL + H 就可以看到类的层次结构了(很重要,不然等会很多继承和实现会把你绕晕的)
类关系:

类关系图:

类关系UML图:

二、代码实现
我这边就按代码层次结构从上到下来展示代码示例
BeanDefinition
定义一个被 Spring 容器管理的 Bean 对象
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;
}
}
2.1 单例注册接口定义和实现
SingletonBeanRegistry
SingletonBeanRegistry 类定义了一个获取单例对象的接口
public interface SingletonBeanRegistry {
Object getSingleton(String beanName);
}
DefaultSingletonBeanRegistry
DefaultSingletonBeanRegistry 类实现 getSingleton 方法,又定义了一个受保护的 addSingleton 方法。
具体来说,protected 访问修饰符的访问权限如下:
tips:具体来说,protected 访问修饰符的访问权限如下:
1.类内部:可以访问自身的 protected 成员;
2.同一包内的其他类:可以访问类的 protected 成员;
3.包的子类:可以访问父类的 protected 成员,前提是子类与父类不在同一个包中;
4.包的非子类:无法访问类的 protected 成员。
import com.lin.test.springframework.beans.factory.config.SingletonBeanRegistry;
import java.util.HashMap;
import java.util.Map;
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
private Map<String, Object> singletonObjects = new HashMap<>();
@Override
public Object getSingleton(String beanName) {
return singletonObjects.get(beanName);
}
protected void addSingleton(String beanName, Object singletonObject) {
singletonObjects.put(beanName, singletonObject);
}
}
2.2 抽象类定义模板方法
BeanFactory
BeanFactory 的定义由 AbstractBeanFactory 抽象类实现接口的 `getBean() 方法
public interface BeanFactory {
Object getBean(String name);
}
AbstractBeanFactory
AbstractBeanFactory首先继承了DefaultSingletonBeanRegistry,也就具备了使用单例注册类方法。- 接下来很重要的一点是关于接口
BeanFactory的实现,在方法getBean的实现过程中可以看到,主要是对单例Bean对象的获取以及在获取不到时需要拿到Bean的定义做相应Bean实例化操作。那么getBean并没有自身的去实现这些方法,而是只定义了调用过程以及提供了抽象方法getBeanDefinition和createBean,由实现此抽象类的其他类做相应实现。 - 后续继承抽象类
AbstractBeanFactory的类有两个,包括:AbstractAutowireCapableBeanFactory、DefaultListableBeanFactory,这两个类分别做了相应的实现处理
import com.lin.test.springframework.beans.factory.BeanFactory;
import com.lin.test.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.BeansException;
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {
@Override
public Object getBean(String name) {
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.3 实例化Bean类
- 在
AbstractAutowireCapableBeanFactory类中实现了Bean的实例化操作newInstance - 在处理完
Bean对象的实例化后,直接调用addSingleton方法存放到单例对象的缓存中去。
AbstractAutowireCapableBeanFactory
import com.lin.test.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.BeansException;
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
Object bean;
try {
bean = beanDefinition.getBeanClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new BeansException("Instantiation of bean failed", e) {
};
}
addSingleton(beanName, bean);
return bean;
}
}
2.4 核心类实现
DefaultListableBeanFactory
DefaultListableBeanFactory在Spring源码中也是一个非常核心的类,在我们目前的实现中也是逐步贴近于源码,与源码类名保持一致。DefaultListableBeanFactory继承了AbstractAutowireCapableBeanFactory类,也就具备了接口BeanFactory和AbstractBeanFactory等一连串的功能实现。所以有时候你会看到一些类的强转,调用某些方法,也是因为你强转的类实现接口或继承了某些类。- 除此之外这个类还实现了接口
BeanDefinitionRegistry中的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法,当然你还会看到一个getBeanDefinition的实现,这个方法我们文中提到过它是抽象类AbstractBeanFactory中定义的抽象方法。现在注册Bean定义与获取Bean定义就可以同时使用了,是不感觉这个套路还蛮深的。接口定义了注册,抽象类定义了获取,都集中在DefaultListableBeanFactory中的beanDefinitionMap里
import com.lin.test.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.BeansException;
import java.util.HashMap;
import java.util.Map;
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry {
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
beanDefinitionMap.put(beanName, beanDefinition);
}
@Override
public 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;
}
}
三、测试
定义一个测试的业务类
public class UserService {
public void queryUserInfo(){
System.out.println("查询用户信息");
}
}
import com.lin.test.bean.UserService;
import com.lin.test.springframework.beans.factory.config.BeanDefinition;
import com.lin.test.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Objects;
@SpringBootTest
class SpringframeworkTest {
@Test
public void testBeanFactory() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinition beanDefinition = new BeanDefinition(UserService.class);
beanFactory.registerBeanDefinition("userService", beanDefinition);
UserService userService = (UserService) beanFactory.getBean("userService");
userService.queryUserInfo();
UserService userService_singleton = (UserService) beanFactory.getBean("userService");
userService_singleton.queryUserInfo();
boolean equals = Objects.equals(userService, userService_singleton);
System.out.println(equals);
}
}
输出:
查询用户信息
查询用户信息
true
这里会有两次测试信息,一次是获取 Bean 时直接创建的对象,另外一次是从缓存中获取的实例化对象。
总结,在 Spring Bean 容器的实现类中要重点关注类之间的职责和关系,几乎所有的程序功能设计都离不开接口、抽象类、实现、继承,而这些不同特性类的使用就可以非常好的隔离开类的功能职责和作用范围。而这样的知识点也是在学习手写 Spring Bean 容器框架过程非常重要的知识。

浙公网安备 33010602011771号