手撸Spring系列一IOC搭建
前言
该项目从bugstack 小傅哥哪里学的。 本文只是记录编写过程和自己的一些心得体会。1. IOC的核心之BeanFactory
1.1 BeanFactory初体验
首先我们需要思考spring的IOC容器的核心在哪里,先不管它的设计是多么的复杂,代码是怎样的抽象。我们需要明确ioc的核心,控制反转,将对象的创建权交由spring来管理,那么这个过程是怎样的呢?
就是我们将自己需要的对象按照ioc容器的Bean定义进行装配,注册到ioc中,程序运行,ioc容器加载Bean定义并获取实例对象,供我们使用。下面用一个简单的案例来描述这一过程。
package com.xzq.springframework.beans.factory.config;
import lombok.Data;
@Data
public class BeanDefinition {
private Class beanClass;
public BeanDefinition(Class beanClass) {
this.beanClass = beanClass;
}
public Object getBean() {
try {
return beanClass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
package com.xzq.springframework.beans.factory;
public class BeanFactory {
private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
private Map<Class<?>, BeanDefinition> beanDefinitionClassMap = new ConcurrentHashMap<>();
public Object getBean(String name) {
return beanDefinitionMap.get(name).getBean();
}
public <T> T getBean(Class<T> clazz) {
return (T) beanDefinitionClassMap.get(clazz).getBean();
}
public void registerBean(String name, BeanDefinition beanDefinition) {
beanDefinitionMap.put(name, beanDefinition);
beanDefinitionClassMap.put(beanDefinition.getBeanClass(), beanDefinition);
}
}
@Test
public void testBeanFactory() {
BeanFactory beanFactory = new BeanFactory();
BeanDefinition beanDefinition = new BeanDefinition(UserService.class);
beanFactory.registerBean(UserService.class.getName(), beanDefinition);
UserService userService = beanFactory.getBean(UserService.class);
userService.sayHello("xzq");
}
1.2 Bean定义,注册,获取
上节的案例只是简单的描述了ioc的核心功能。当然,ioc没有这么简单。下面我们来使用面向接口编程,模板设计模式来完成Bean的定义,注册,获取。
BeanDefinition的定义
我们需要思考一个Bean在spring容器中的一个过程。
首先加载Bean ,定义Beandefinition, 实例Bean, 依赖注入(属性填充),初始化Bean。
可以简单得分为这五个步骤,那么基于这五个步骤,我们需要在BeanDefinition中定义那些信息呢?
首先实例化Bean,要定义BeanClass,其次依赖注入,我们需要Bean属性的name和需要注入的value;再然后初始化Bean的时候,如果配置了init-method或者实现了InitializingBean需要调用相应的初始化方法。基于这些,我们对BeanDefinition完成以下的定义。
package com.xzq.springframework.beans;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author xzq
* @Description // 属性对象
* @Date 2021/11/24 11:04
* @Version 1.0.0
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PropertyValue {
private String name;
private String value;
}
package com.xzq.springframework.beans;
import cn.hutool.core.util.StrUtil;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* @Author xzq
* @Description //TODO
* @Date 2021/11/24 11:04
* @Version 1.0.0
**/
@Data
public class PropertyValues {
private List<PropertyValue> propertyValueList = new ArrayList<>();
public void addPropertyValue(PropertyValue propertyValue) {
propertyValueList.add(propertyValue);
}
public PropertyValue[] getPropertyValues() {
return propertyValueList.toArray(new PropertyValue[0]);
}
public List<PropertyValue> getPropertyValueList() {
return propertyValueList;
}
/**
* 根据名称获取PropertyValue
*/
public PropertyValue getPropertyValue(String name) {
if (StrUtil.isEmpty(name)) {
return null;
}
for (PropertyValue propertyValue : propertyValueList) {
if (propertyValue.getName().equals(name)) {
return propertyValue;
}
}
return null;
}
}
package com.xzq.springframework.beans.factory.config;
import com.xzq.springframework.beans.PropertyValues;
import lombok.Data;
/**
* @Author xzq
* @Description // Bean的实例化信息定义
* @Date 2021/11/24 10:02
* @Version 1.0.0
**/
@Data
public class BeanDefinition {
/**
* bean的Class对象,实例化时需要进行反射调用创建对象
*/
private Class beanClass;
/**
* 依赖注入所需要的信息
*/
private PropertyValues propertyValues;
/**
* 初始化和销毁方法
*/
private String initMethod;
private String destroyMethod;
}
BeanFactory系列定义
在spring中,对于设计模式和面向接口编程玩的比较溜,看过源码的朋友都知道,spring的设计十分超前,遵循单一职责,每一块的功能点划分的非常细,都会交由相应的实现来完成。
对于ioc容器来说,我们需要注册BeanDefinition到ioc中,ioc会实例Bean,并将实例化后的Bean加入一级缓存中,这一过程由SinletonBeanRegister完成。
package com.xzq.springframework.beans.factory.config;
/**
* @Author xzq
* @Description // 单例Bean注册职责接口
* @Date 2021/11/24 11:21
* @Version 1.0.0
**/
public interface SingletonBeanRegistry {
void registerSingleton(String beanName, Object singletonObject);
Object getSinleton(String beanName);
}
package com.xzq.springframework.beans.factory.config;
import cn.hutool.core.lang.Assert;
import java.util.HashMap;
import java.util.Map;
/**
* @Author xzq
* @Description // 单例Bean注册的实现类
* @Date 2021/11/24 11:26
* @Version 1.0.0
**/
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry{
/**
* 一级缓存 ,完成实例化和初始化之后的缓存Bean实例
*/
private Map<String, Object> singletonObjects = new HashMap<>();
@Override
public void registerSingleton(String beanName, Object singletonObject) {
Assert.notNull(beanName, "Bean name must not be null");
Assert.notNull(singletonObject, "Singleton object must not be null");
singletonObjects.put(beanName, singletonObject);
}
@Override
public Object getSinleton(String beanName) {
return singletonObjects.get(beanName);
}
}
package com.xzq.springframework.beans.factory.support;
import com.xzq.springframework.beans.BeansException;
import com.xzq.springframework.beans.factory.BeanFactory;
import com.xzq.springframework.beans.factory.config.BeanDefinition;
import com.xzq.springframework.beans.factory.config.DefaultSingletonBeanRegistry;
/**
* @Author xzq
* @Description // 抽象类定义模板方法
* @Date 2021/11/24 11:34
* @Version 1.0.0
**/
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {
@Override
public Object getBean(String beanName, Object... args) throws BeansException {
return doGetBean(beanName, args);
}
@Override
public Object getBean(String beanName) throws BeansException {
return doGetBean(beanName, null);
}
/**
* doGetBean的工作流程
* 1,从缓存中获取
* 2,获取Bean实例化信息
* 3,创建Bean实例
*
* @param beanName
* @return
* @throws BeansException
*/
public Object doGetBean(String beanName, Object... args) {
Object bean = getSinleton(beanName);
if (bean != null) {
return bean;
}
BeanDefinition beanDefinition=getBeanDefinition(beanName);
return createBean(beanName, beanDefinition);
}
protected abstract Object createBean(String name, BeanDefinition beanDefinition);
protected abstract BeanDefinition getBeanDefinition(String name);
}
package com.xzq.springframework.beans.factory.support;
import com.xzq.springframework.beans.BeansException;
import com.xzq.springframework.beans.factory.config.BeanDefinition;
/**
* @Author xzq
* @Description // 自动装配Bean抽象类 负责完成创建Bean的全过程
* @Date 2021/11/24 11:44
* @Version 1.0.0
**/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory{
/**
* 创建Bean的核心方法
* 1,实例化Bean
* 2, 依赖注入
* 3,初始化Bean
* 4, 加入Bean实例缓存中(一级缓存)
* @param name
* @param beanDefinition
* @return
*/
@Override
protected Object createBean(String name, BeanDefinition beanDefinition) {
Object bean = null;
try {
bean = beanDefinition.getBeanClass().newInstance();
} catch (Exception e) {
throw new BeansException("bean instantiation failed");
}
//注册到缓存单例
registerSingleton(name, bean);
return bean;
}
}
BeanDefinitionRegister定义
package com.xzq.springframework.beans.factory.support;
import com.xzq.springframework.beans.factory.config.BeanDefinition;
public interface BeanDefinitionRegister {
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
boolean containsBeanDefinition(String beanName);
}
package com.xzq.springframework.beans.factory.support;
import com.xzq.springframework.beans.BeansException;
import com.xzq.springframework.beans.factory.config.BeanDefinition;
import java.util.HashMap;
import java.util.Map;
/**
* @Author xzq
* @Description // BeanFactory系列的核心类 ,聚焦了大多数BeanFactory功能, 也是spring中实际的BeanFactory实现。
* @Date 2021/11/24 11:50
* @Version 1.0.0
**/
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegister{
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
@Override
protected BeanDefinition getBeanDefinition(String name) {
BeanDefinition beanDefinition = beanDefinitionMap.get(name);
if (beanDefinition==null){
throw new BeansException(name + " is not defined");}
return beanDefinition;
}
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
beanDefinitionMap.put(beanName, beanDefinition);
}
@Override
public boolean containsBeanDefinition(String beanName) {
return beanDefinitionMap.containsKey(beanName);
}
}
2. 测试
@Test
public void test_ioc() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanClass(UserService.class);
beanFactory.registerBeanDefinition("userService", beanDefinition);
UserService userService = (UserService)beanFactory.getBean("userService");
userService.sayHello("xzq");
}