手撸spring源码--设计模式实现spring容器

一、实现简单的spring容器

1.背景

(1)spring容器是什么?

用于承载对象的容器。对于spring容器来说,bean对象应该以类似零件方式拆解后放到bean定义中,对象解偶操作更有利于spring管理bean。

当bean信息被定义后,再由spring统一装配,包括bean初始化、属性填充等,最后得到完整的实例化对象。

(2)hashmap

hashmap是一种基于扰动函数、负载因子、红黑树转换等技术,形成的拉链寻址的数据结构,它能让数据更加散列的分布在哈希桶以及碰撞时形成的链表和红黑树上。

 2.设计spring容器

选择容器数据结构:容器需要存放bean名称和对象,使用hashmap更合适。

除此之外,spring容器还需要有简单功能:能够实现bean定义,bean注册,bean获取。

  • - 在spring中,beandefinition会包含singleton、beanclassname等,但是此处只定义一个Object对象存放bean对象。
  • - bean注册:把数据放到hashmap中,此处hashmap存放了定义bean信息的beanDefinition对象。
  • - bean获取:bean名字是key,初始化完毕容器后,即可直接获取bean。

3.简单实现

定义两个类,分别如下:

  •  BeanDefinition,用于定义 Bean 实例化信息,现在的实现是以一个 Object 存放对象
  •  BeanFactory,代表了 Bean 对象的工厂,可以存放 Bean 定义到 Map 中以及获取。
// 1.初始化 BeanFactory
BeanFactory beanFactory = new BeanFactory();

// 2.注册 bean
BeanDefinition beanDefinition = new BeanDefinition(new UserService());
beanFactory.registerBeanDefinition("userService", beanDefinition);

// 3.获取 bean
UserService userService = (UserService) beanFactory.getBean("userService");
userService.queryUserInfo();
//可以看出,其思路和spring中自定义工厂模式获取bean类似。


 

二、设计模式实现spring容器

1.背景

其实编码方式主要依托于:接口定义、类实现接口、抽象类实现接口、继承类、继承抽象类,而这些操作方式可以很好的隔离开每个类的基础功能、通用功能和业务功能,当类的职责清晰后,你的整个设计也会变得容易扩展和迭代。

2.目标与设计

目标:完善基础容器框架结构

设计:

spring注册bean时实际上只注册一个类信息,需要修改BeanDefinition属性为class。此时需要做的就是在获取 Bean 对象时,首先判断当前获取的对象是否已经在内存(容器)中,不在时需要对Bean对象进行实例化操作,然后注册到容器中。

(1)重新设计BeanFactory系列接口

手撸spring源码--设计模式实现spring容器_第1张图片

 类图解释:

  • BeanFactory:Bean工厂接口。Bean工厂接口只声明和bean创建有关的方法,例如通过类名等方式获取bean的方法等。
  • SingletonBeanRegistry:注册单例Bean接口。注册Bean的借口只声明和bean注册有关的方法,例如注册、获取bean的方法。
  • DefaultSingletonBeanRegistry:实现SingletonBeanRegistry接口的类。该类新增了注册单例bean的方法。
  • AbstractBeanFactory:抽象Bean工厂方法。抽象工厂类必定实现了BeanFactory接口获取bean的getBean方法的。抽象类不能直接创建对象,该类还需定义获取类信息、创建bean的抽象方法,分别是getBeanDefinition()和createBean()抽象方法,由其子类实现。
    • getBean()方法实现,可以通过bean注册类从容器中获取。如果容器中不存在,则需要根据类定义信息BeanDefinition创建bean对象。
  • AbstractAutowireCapableBeanFactory:抽象Bean工厂的子抽象类。 该类实现了AbstractBeanFactory的创建Bean的createBean()方法,通过反射方式实现。
  • DefaultListableBeanFactory:是最终Bean工厂实现类,继承自AbstractAutowireCapableBeanFactory实现了获取Bean定义信息的getBeanDefinition()方法;实现了BeanDefinitionRegistry的注册Bean定义信息的方法。

(2)代码实现

//BeanFactory接口
public interface BeanFactory {
	 public Object getBean(String name);
}

//bean获取的SingletonBeanRegistry接口
public interface SingletonBeanRegistry {
	 Object getSingleton(String beanName);
}

//bean定义信息BeanDefinition类
public class BeanDefinition {
	private Class beanClass;//bean的实例化操作放到容器中处理
	public BeanDefinition(Class beanClass) {
		this.setBeanClass(beanClass);
	}
	public Class getBeanClass() {
		return beanClass;
	}
	public void setBeanClass(Class beanClass) {
		this.beanClass = beanClass;
	}
}

//Bean注册/获取接口实现类
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry{
	private Map singletonObjects = new HashMap<>();
	@Override
	public Object getSingleton(String beanName) {
		return singletonObjects.get(beanName);
	}
	protected void addSingleton(String beanName,Object singletonObject) {
		singletonObjects.put(beanName, singletonObject);
	}

}


//实现BeanFactory、继承Bean注册获取的抽象类。新增了创建bean、获取bean定义信息方法
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory{

	@Override
	public Object getBean(String name) throws BeansException{
		Object bean = getSingleton(name);//从DefaultSingletonBeanRegistry中根据name获取对象
		if(bean != null) return bean;
		//获取不到情况下,则根据bean定义信息创建bean。getBean 并没有自身的去实现这些方法,而是只定义了调用过程以及提供了抽象方法,由实现此抽象类的其他类做相应实现。
		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;
}

//AbstractAutowireCapableBeanFactory实现了AbstractBeanFactory中的createBean抽象方法
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory{
	private static final Logger logger = LoggerFactory.getLogger(AbstractAutowireCapableBeanFactory.class);
	@Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
        Object bean = null;
        try {
            bean = beanDefinition.getBeanClass().newInstance();//这里是无参构造对象,如果是有参数的,则需要获取构造方法,根据构造方法ctor创建对象。
        } catch (InstantiationException | IllegalAccessException e) {
//            throw new BeansException("Instantiation of bean failed", e);
        	logger.error("Instantiation of bean failed",e);
        }
        //创建bean后,直接添加当前bean到spring容器中
        addSingleton(beanName, bean);
        return bean;
    }
}

//bean定义信息注册接口
public interface BeanDefinitionRegistry {
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
}

//最终实现类
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry{
	private Map beanDefinitionMap = new HashMap<>();
	@Override
	protected BeanDefinition getBeanDefinition(String beanName) throws BeansException {
		BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
		if (beanDefinition == null) 
			throw new BeansException1("No bean named '" + beanName + "' is defined");
        return beanDefinition;
	}
	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
		beanDefinitionMap.put(beanName, beanDefinition);
	}

}

(3)测试代码

@Test
public void test_BeanFactory(){
    // 1.初始化 BeanFactory
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    // 2.注册 bean
    BeanDefinition beanDefinition = new BeanDefinition(UserService.class);
    beanFactory.registerBeanDefinition("userService", beanDefinition);
    // 3.第一次获取 bean
    UserService userService = (UserService) beanFactory.getBean("userService");
    userService.queryUserInfo();
    // 4.第二次获取 bean from Singleton
    UserService userService_singleton = (UserService) beanFactory.getBean("userService");
    userService_singleton.queryUserInfo();
}


//测试类
public class UserService {

    public void queryUserInfo(){
        System.out.println("查询用户信息");
    }

}

结果:

测试打印userService和userService_singleton的hashcode,两者一样。

hashmap+从内存判断决定了单例对象。

3.思考与收获

  • 设计接口/类时,其职责按照接口/类名字决定其功能,职责单一。
  • 为实现spring容器,注册/获取bean对象,将功能实现拆分为多个接口/类,方便后续扩展,并且使用抽象类实现部分功能。
  • 抽象类的好处就在于:所有子类使用的都是相同的方法原型,强迫子类必须完成抽象父类规定的“标准”行为。


————————————————
版权声明:本文为CSDN博主「小傅哥」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/generalfu/article/details/117199830

你可能感兴趣的:(spring系列)