spring 手写简单的IOC

1、Spring核心容器

spring 手写简单的IOC_第1张图片

#1)spring-beans & spring-core
	是spring核心模块,包含【控制反转】和【依赖注入】。
    BeanFactory使用控制反转对应用程序的配置和依赖性规范与实际应用程序分离。
    BeanFactory属于【延时加载】,实例化容器不会实例化bean,而是在bean使用时,才会对bean实例化与依赖关系的装配
    
    //不会实例化,不会调用构造方法
    BeanFactory context = new XmlBeanFactory(new ClassPathResource("application.xml"));
    //使用时实例化,调用构造方法
    UserService userService = context.getBean("userService", UserService.class);

#2)spring-context
	构架于核心模块之上,【扩展】了BeanFactory,添加生命周期、框架事件体系、资源加载透明化(还包括了邮件访问、远程访问、任务调度)
	ApplicationContext是核心接口,【继承BeanFactory】,但实例化容器之后会【自动】对所有的单实例bean实例化和依赖关系的装配

	//会实例化bean,调用其构造方法
	ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
    
#3)spring-context-support
	【IOC容器】和【IOC子容器】的扩展--springMvc

#4)spring-context-indexer
	【类管理组件】和【classpath扫描组件】--扫描注解
	
#5)spring-expression(spEL)
	同一表达式语言(EL)的扩展模块,查询、管理运行中的对象,方便的调用对象方法。
	

2、IOC分析

1)BeanFactory(管理bean及其关系)

spring 手写简单的IOC_第2张图片

IOC容器【简单工厂+配置文件】
	#BeanFactory定义IOC最基本的功能规范
		## ListableBeanFactory(重要)	 --bean可列表化(用列表存储)
		## HierarchicalBeanFactory	   	--有继承关系的
		## AutowireCapableBeanFactor	--自动装配规则
			--【实现类】DefaultListableBeanFactory
//BeanFactory接口
public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";
	//获取bean
    Object getBean(String var1) throws BeansException;
	//是否包含bean
    boolean containsBean(String var1);
	//是否是单例 
    boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;

    @Nullable
    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
}

spring 手写简单的IOC_第3张图片

2)BeanDefinition(封装xml中的标签)

spring 手写简单的IOC_第4张图片

# 解析xml文件标签,封装在BeanDefinition对象中

3)BeanDefinitionReader(xml标签解析)

spring 手写简单的IOC_第5张图片

//BeanDefinitionReader接口
public interface BeanDefinitionReader {
    //获取注册器对象
    BeanDefinitionRegistry getRegistry();
	//从指定资源中加载bean到BeanDefinition中
    int loadBeanDefinitions(Resource var1) throws BeanDefinitionStoreException;
    int loadBeanDefinitions(Resource... var1) throws BeanDefinitionStoreException;
    int loadBeanDefinitions(String var1) throws BeanDefinitionStoreException;
    int loadBeanDefinitions(String... var1) throws BeanDefinitionStoreException;
}

4)BeanDefinitionRegistry(存储所有bean)

spring 手写简单的IOC_第6张图片

# 配置文件定义多个bean标签,解析的BeanDefinition存储在注册中心BeanDefinitionRegistry
//BeanDefinitionRegistry接口
public interface BeanDefinitionRegistry extends AliasRegistry {
    //注册BeanDefinition
    void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
	//删除指定名称BeanDefinition
    void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
	//获取指定名称BeanDefinition
    BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
	//判断是否存在BeanDefinition
    boolean containsBeanDefinition(String var1);
	//获取所有bean名称BeanDefinition
    String[] getBeanDefinitionNames();
    
    int getBeanDefinitionCount();
    boolean isBeanNameInUse(String var1);
}
//DefaultListableBeanFactory实现类
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
	//存放bean
    private final Map<String, BeanDefinition> beanDefinitionMap;
    public DefaultListableBeanFactory() {
        this.beanDefinitionMap = new ConcurrentHashMap(256);
    }
}

5)创建容器(refresh方法)

	ClassPathXmlApplicationContext对Bean对象的装再是从refresh()方法开始的,是一个模板方法,规定了IOC执行流程,其逻辑交由子类实现。
	他对Bean资源的载入,ClassPathXmlApplicationContext通过调用父类的AbstractApplicationContext的refresh()方法启动整个IOC容器对Bean的装载过程。

3、手写IOC

spring 手写简单的IOC_第7张图片

<--! maven 依赖-->
<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
    <version>1.18.24version>
    <scope>compilescope>
dependency>
<dependency>
    <groupId>dom4jgroupId>
    <artifactId>dom4jartifactId>
    <version>1.1version>
dependency>

1)定义Bean相关的POJO类

① PropertyValue类
#1)封装property标签

#2)包含name(注入名称)、ref(引用名称)、value(基本数据类型值)
//property标签 封装类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PropertyValue {
    private String name;
    private String ref;
    private String value;
}
② PropertyValues类
#1)用来存储bean对应的多个property标签
//管理多个property标签 封装类
@Data
public class MutablePropertyValues implements Iterable<PropertyValue>{
    private final List<PropertyValue> propertyValueList;

    public MutablePropertyValues() {
        this.propertyValueList = new ArrayList<>();
    }
    public MutablePropertyValues(List<PropertyValue> propertyValueList) {
        if (propertyValueList == null){
            this.propertyValueList = new ArrayList<>();
        }else {
            this.propertyValueList = propertyValueList;
        }
    }
    @Override
    public Iterator<PropertyValue> iterator() {
        return propertyValueList.iterator();
    }
    //获取所有数组
    public PropertyValue[] getPropertyValueList(){
        return propertyValueList.toArray(new PropertyValue[0]);
    }
    //获取指定名称
    public PropertyValue getPropertyValue(String name){
        return propertyValueList.stream().filter(t->name.equals(t.getName())).findFirst().orElse(null);
    }
    //是否包含指定名称
    public boolean isContain(String name){
        return getPropertyValue(name) != null;
    }
    //判断是否为空
    public boolean isEmpty(){
        return propertyValueList.isEmpty();
    }
    //添加
    public MutablePropertyValues addPropertyValue(PropertyValue propertyValue){
        List<String> list = propertyValueList.stream()
                .map(PropertyValue::getName)
                .filter(t -> propertyValue.getValue().equals(t))
                .collect(Collectors.toList());
        //判断bean是否已经存在
        if (!list.isEmpty()){
            throw new RuntimeException("bean名称重复");
        }
        propertyValueList.add(propertyValue);
        return this;//方便链式编程
    }
}
③ BeanDefinition类
#1)封装bean信息

#2)包含id(bean名称)、class(全类型)、property(注入的属性)
//管理多个property标签 封装类
@Data
public class BeanDefinition {
    private String id;
    public String clazz;
    private MutablePropertyValues mutablePropertyValues;
    public BeanDefinition(){
        mutablePropertyValues = new MutablePropertyValues();
    }
}

2)定义注册表相关的类

① BeanDefinitionRegiesty接口
#1)包含注册、删除、获取、个数、所有名称5个方法
//注册接口
public interface BeanDefinitionRegistry {
    void registryBeanDefinition(String beanName, BeanDefinition beanDefinition);
    void removeBeanDefinition(String beanName);
    BeanDefinition getBeanDefinition(String beanName);
    boolean containBeanDefinition(String beanName);
    int getBeanDefinitionCount();
    String[] getBeanDefinitionNames();
}
② SimpleBeanDefinitionRegiesty实现类
//注册实现类
public class SimpleBeanDefinitionRegistry implements BeanDefinitionRegistry{
    private Map<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
    @Override
    public void registryBeanDefinition(String beanName, BeanDefinition beanDefinition) {
        beanDefinitionMap.put(beanName, beanDefinition);
    }
    @Override
    public void removeBeanDefinition(String beanName) {
        beanDefinitionMap.remove(beanName);
    }
    @Override
    public BeanDefinition getBeanDefinition(String beanName) {
        return beanDefinitionMap.get(beanName);
    }
    @Override
    public boolean containBeanDefinition(String beanName) {
        return beanDefinitionMap.containsKey(beanName);
    }
    @Override
    public int getBeanDefinitionCount() {
        return beanDefinitionMap.size();
    }
    @Override
    public String[] getBeanDefinitionNames() {
        return beanDefinitionMap.keySet().toArray(new String[0]);
    }
}

3)定义解释器相关的类

① BeanDefinfitionReader接口
#1)解析xml配置文件

#2)在注册表中注册bean 
//解析xml、注册bean 接口
public interface BeanDefinitionReader {
    BeanDefinitionRegistry getRegistry();
    void loadBeanDefinitions(String configLocation) throws Exception;
}
② XmlBeanDefinitionReader实现类
//解析xml、注册bean 实现类
public class XmlBeanDefinitionReader implements BeanDefinitionReader {
    private BeanDefinitionRegistry beanDefinitionRegistry;

    public XmlBeanDefinitionReader() {
        this.beanDefinitionRegistry = new SimpleBeanDefinitionRegistry();
    }

    @Override
    public BeanDefinitionRegistry getRegistry() {
        return beanDefinitionRegistry;
    }
    @Override
    public void loadBeanDefinitions(String configLocation) throws Exception {
        //dom4j读取beans根元素
        SAXReader saxReader = new SAXReader();

        InputStream stream = XmlBeanDefinitionReader.class.getClassLoader().getResourceAsStream(configLocation);
        Document document = saxReader.read(stream);
        Element beans = document.getRootElement();
        List<Element> bean = beans.elements("bean");
        //遍历beans
        for (Element element : bean) {
            BeanDefinition beanDefinition = new BeanDefinition();
            String id = element.attributeValue("id");
            beanDefinition.setId(id);
            beanDefinition.setClazz(element.attributeValue("class"));
            //遍历所有property
            MutablePropertyValues propertyValues = new MutablePropertyValues();
            List<Element> properties = element.elements("property");
            for (Element property : properties) {
                String name = property.attributeValue("name");
                String ref = property.attributeValue("ref");
                String value = property.attributeValue("value");
                PropertyValue propertyValue = new PropertyValue(name, ref, value);

                propertyValues.addPropertyValue(propertyValue);
            }
            beanDefinition.setMutablePropertyValues(propertyValues);
            //注册
            beanDefinitionRegistry.registryBeanDefinition(id, beanDefinition);
        }
    }
}

4)IOC相关类

① BeanFactory 接口
#1)IOC容器同一规范, 获取bean对象
//IOC父容器
public interface BeanFactory {
    Object getBean(String name) throws Exception;
    <T> T getBean(String name, Class<? extends T> type) throws Exception;
}
② ApplicationContext 接口
#1)非延时的,refresh()方法

#2)用来加载配置文件、bean对象创建
//非延时加载 接口
public interface ApplicationContext extends BeanFactory {
    void refresh() throws Exception;
}
③ AbstractApplicationContext 接口
#1)继承ApplicationContext接口,即非延时加载,定义Map作为bean对象存储的容器

#2) 声明BeanDefinitionReader类型变量,xml解析,单一职责原则

#3)BeanDefinitionReader对象的创建交由子类实现,因为只有子类才知道创建的那个BeanDefinitionReader子类实现对象 
//用于非延时加载
public abstract class AbstractApplicationContext implements ApplicationContext {
    //解析器(包含了解析xml、封装bean对象)
    protected BeanDefinitionReader beanDefinitionReader;
    //bean对象map
    protected Map<String, Object> singletonObject = new ConcurrentHashMap<>();
    //配置文件的路径
    protected String configLocation;
    @Override
    public void refresh() throws Exception {
        //封装BeanDefinition对象
        beanDefinitionReader.loadBeanDefinitions(configLocation);
        //初始化bean
        finishBeanInitialization();
    }
    private void finishBeanInitialization() throws Exception{
        BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();
        String[] beanNames = registry.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            getBean(beanName);
        }
    }
}
④ ClassPathXmlApplicationContext 类
#1)在构造方法中,创建BeanDefinitionReader对象

#2)在构造方法中,调用refresh()方法【配置文件加载、创建bean对象】

#3)重写getBean()方法,实现依赖注入
//IOC具体实现类
public class ClassPathXmlApplicationContext extends AbstractApplicationContext{
    //构造方法 加载bean
    public ClassPathXmlApplicationContext(String configLocation) {
        this.configLocation = configLocation;
        beanDefinitionReader = new XmlBeanDefinitionReader();
        try {
            this.refresh();
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    @Override
    public Object getBean(String beanName) throws Exception {
        //如果有,直接返回
        Object obj = singletonObject.get(beanName);
        if (obj != null){
            return obj;
        }
        //如果没有,加载bean对象(反射创建对象)
        BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();
        BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);
        String className = beanDefinition.getClazz();

        Class clazz = Class.forName(className);
        Object beanObj = clazz.newInstance();
        //注册依赖对象
        MutablePropertyValues mutablePropertyValues = beanDefinition.getMutablePropertyValues();
        for (PropertyValue property : mutablePropertyValues) {
            String name = property.getName();
            String ref = property.getRef();
            String value = property.getValue();
            //ref 引用
            if (ref!=null && !"".equals(ref)){
                Object bean = getBean(ref);
                String methodName = StringUtils.getSetterName(name);
                Method[] methods = clazz.getMethods();
                for (Method method : methods) {
                    if (method.getName().equals(methodName)){
                        method.invoke(beanObj, bean);
                        break;
                    }
                }
            }
            //vaule 值
            if (value!=null && !"".equals(value)){
                String methodName = StringUtils.getSetterName(name);
                Method methods = clazz.getMethod(methodName, String.class);
                methods.invoke(beanObj, value);
            }
        }
        //保存bean
        singletonObject.put(beanName, beanObj);

        return beanObj;
    }

    @Override
    public <T> T getBean(String name, Class<? extends T> type) throws Exception {
        Object bean = getBean(name);
        if (bean == null){
            return null;
        }
        return type.cast(bean);
    }
}

你可能感兴趣的:(Java笔记,spring,java,后端)