自研Spring项目小总结


一、Spring是什么

  • spring其实是一个容器框架,可以用来配置各种bean(配置文件xml),并且可以维护bean与bean的关系,当我们需要某个bean的时候,只需要getBean(id) 就可以了。
  • 这里getBean是以反射为基础的,因为一开始并不知道我要初始化的类对象是什么,只能通过xml文件解析出类的路径,所以不能用new来创建对象。
  • 没有spring之前,我们都是通过代码来维护各个对象之间的联系,并且设置属性,这样就可以更加专注于业务逻辑了。
  • 不用spring写一个Tom和Jim打架了
public class Dog {
	
	private String name;
	
	public Dog(String name) {
		this.name = name;
	}
	
	public String getName() {
		return name;
	}
}

public class Cat {

	private Dog dog ;
	private String name;
	
	public Cat(Dog dog , String name) {
		this.dog = dog;
		this.name = name;
	}
	
	public String getName() {
		return name;
	}
	
	public void fight() {
		System.out.println(dog.getName() + "和" + name + "打起来了");
	}
	//这里是通过代码来维护 dog 和 cat 之间的关系的,也是通过代码来设置
	public static void main(String[] args) {
		//dog和cat的关系要自己配置
		Dog dog = new Dog("Jim");
		Cat cat = new Cat(dog,"Tom");
		cat.fight();		
	}
}

  • 使用spring框架
  • xml配置文件
		<bean id="cat" class="test.Cat">
            <constructor-arg name="dog" ref="dog"></constructor-arg>
            <constructor-arg name="name" value="Tom"></constructor-arg>
        </bean>

        <bean id="dog" class="test.Dog">
            <constructor-arg name="name" value="Jim"></constructor-arg>
        </bean>
  • 实例都有spring容器来进行创建。这就可以专注于业务逻辑了
    @Test
    public void test(){
        ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("bean5.xml");

        Cat cat = applicationContext.getBean("cat",Cat.class);
        cat.fight();
    }

二、源码分析

  • 其实我们看到的ApplicationContext就是容器
 ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("bean5.xml");

  • 以上代码就是在ApplicationContext中注册了bean5.xml中配置的类信息
  • 所以,上述代码完成了两件事,解析xml文件,将其中的类信息存储到容器中去。
  • 等到需要的时候就按照id和类型信息将其取出。
    在这里插入图片描述
  • 上图是ApplicationContext的类的继承结构
  • 现在来看看ClassPathXmlApplicationContext的源码
  • ClassPathXmlApplicationContext中有很多构造器,但是最后都会走到下图的构造器中
  • setConfigLocations(configLocations);是根据配置文件的路径来处理配置文件的方法
public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {

		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}
  • refresh();比较关键
  • 这个方法主要做的就是将xml文件解析出来,并且将bean注册到容器中
public void refresh() throws BeansException, IllegalStateException {
   // 来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作,那不就乱套了嘛
   synchronized (this.startupShutdownMonitor) {

      // 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
      prepareRefresh();

      // 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
      // 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
      // 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
      // 这块待会会展开说
      prepareBeanFactory(beanFactory);

      try {
         // 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
         // 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】

         // 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
         // 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
         postProcessBeanFactory(beanFactory);
         // 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
         invokeBeanFactoryPostProcessors(beanFactory);

         // 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
         // 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
         // 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
         registerBeanPostProcessors(beanFactory);

         // 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
         initMessageSource();

         // 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
         initApplicationEventMulticaster();

         // 从方法名就可以知道,典型的模板方法(钩子方法),
         // 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
         onRefresh();

         // 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过
         registerListeners();

         // 重点,重点,重点
         // 初始化所有的 singleton beans
         //(lazy-init 的除外)
         finishBeanFactoryInitialization(beanFactory);

         // 最后,广播事件,ApplicationContext 初始化完成
         finishRefresh();
      }

      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }

         // Destroy already created singletons to avoid dangling resources.
         // 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
         destroyBeans();

         // Reset 'active' flag.
         cancelRefresh(ex);

         // 把异常往外抛
         throw ex;
      }

      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
      }
   }
}

自研Spring框架

  • 这个项目其实大体上很容易理解,就是将xml解析出来的内容交给自己研发出来的spring框架去处理,为了是代码的质量更高一点,所以应用了很多的设计模式,使不同的接口或者抽象类实现不同的功能。

Xml解析

  • 这个很简单就是通过xml文件的路径,获得Document,然后进行解析

Bean

  • Bean在我看来其实就是源码里面的BeanDefinition
  • 以下是我定义的BeanDefinition
public class BeanDefinition {

    private Class beanClass;
	
	//Bean的属性
    private PropertyValues propertyValues;
	
	//初始化方法的名字
    private String initMethodName;
    
    //销毁后方法的名字
    private String destroyMethodName;

    public BeanDefinition(Class beanClass) {
        this.beanClass = beanClass;
        this.propertyValues = new PropertyValues();
    }

    public BeanDefinition(Class beanClass, PropertyValues propertyValues) {
        this.beanClass = beanClass;
        this.propertyValues = propertyValues != null ? propertyValues : new PropertyValues();
    }

    public Class getBeanClass() {
        return beanClass;
    }

    public void setBeanClass(Class beanClass) {
        this.beanClass = beanClass;
    }

    public PropertyValues getPropertyValues() {
        return propertyValues;
    }

    public void setPropertyValues(PropertyValues propertyValues) {
        this.propertyValues = propertyValues;
    }

    public String getInitMethodName() {
        return initMethodName;
    }

    public void setInitMethodName(String initMethodName) {
        this.initMethodName = initMethodName;
    }

    public String getDestroyMethodName() {
        return destroyMethodName;
    }

    public void setDestroyMethodName(String destroyMethodName) {
        this.destroyMethodName = destroyMethodName;
    }
}
  • 属性可能有很多个
public class PropertyValues {

    private final List<PropertyValue> propertyValueList = new ArrayList<>();

    public void addPropertyValue(PropertyValue pv) {
        this.propertyValueList.add(pv);
    }

    public PropertyValue[] getPropertyValues() {
        return this.propertyValueList.toArray(new PropertyValue[0]);
    }

    public PropertyValue getPropertyValue(String propertyName) {
        for (PropertyValue pv : this.propertyValueList) {
            if (pv.getName().equals(propertyName)) {
                return pv;
            }
        }
        return null;
    }

}

public class PropertyValue {

    private final String name;

    private final Object value;

    public PropertyValue(String name, Object value) {
        this.name = name;
        this.value = value;
    }

    public String getName() {
        return name;
    }

    public Object getValue() {
        return value;
    }

}

单例注册

  • createBean的时候会先检查下DefaultSingletonBeanRegistry中的singletonObjects是否包含了当前id的Bean,如果有,直接拿出来getSingleton(),如果没有则创建一个Bean实例,然后加入到这个map中去
public interface SingletonBeanRegistry {

    Object getSingleton(String beanName);

}

public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {

    private Map<String, Object> singletonObjects = new HashMap<>();

    private final Map<String, DisposableBean> disposableBeans = new HashMap<>();

    @Override
    public Object getSingleton(String beanName) {
        return singletonObjects.get(beanName);
    }

    protected void addSingleton(String beanName, Object singletonObject) {
        singletonObjects.put(beanName, singletonObject);
    }

    public void registerDisposableBean(String beanName, DisposableBean bean) {
        disposableBeans.put(beanName, bean);
    }
	
	//销毁的方法
    public void destroySingletons() {
        Set<String> keySet = this.disposableBeans.keySet();
        Object[] disposableBeanNames = keySet.toArray();
        
        for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
            Object beanName = disposableBeanNames[i];
            DisposableBean disposableBean = disposableBeans.remove(beanName);
            try {
                disposableBean.destroy();
            } catch (Exception e) {
                throw new BeansException("Destroy method on bean with name '" + beanName + "' threw an exception", e);
            }
        }
    }
}

Bean工厂

  • bean工厂
  • 在本项目中处理bean的所有类就是bean工厂
    在这里插入图片描述
  • 这些就是bean工厂
  • 这些都是基于BeanFactory来实现的

父类接口

BeanFactory
public interface BeanFactory {
	//无参构造器获取对象实例
    Object getBean(String name) throws BeansException;
	//有参构造器获取对象实例
    Object getBean(String name, Object... args) throws BeansException;
	//获取要求类型的对象实例
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

}
ConfigurableListableBeanFactory
  • 看名字,就是配置文件的一些什么东西的集合
public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {

    BeanDefinition getBeanDefinition(String beanName) throws BeansException;
	//提前实例化单例对象
    void preInstantiateSingletons() throws BeansException;
	//注册实现了BeanPostProcessor接口的对象
    void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

}
DisposableBean
  • 销毁方法
public interface DisposableBean {

    void destroy() throws Exception;

}
HierarchicalBeanFactory
  • 分层(就是父类子类加载,目前还没实现)
InitializingBean
  • 初始化
ListableBeanFactory
public interface ListableBeanFactory extends BeanFactory{
	//按照类型返回Bean实例
    <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
    //返回注册表中所有的Bean名称
    String[] getBeanDefinitionNames();

}

config文件夹

在这里插入图片描述

  • 这里主要是一些配置文件
AutowireCapableBeanFactory(自动装配)
  • 这里面实现的就是BeanPostProcessors中的两个方法
//初始化之前执行的方法
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException;

//初始化之后执行的方法
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException;
BeanDefinition
  • 其实就是Bean实例
 ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("bean5.xml");
  • 经过上述代码得到的东西,上述代码就是将BeanDefinition注册到容器中去,容器其实就是一个map,这个map在DefaultListableBeanFactory里面。
BeanFactoryPostProcessor
  • 主要是提供了在所有BeanDefinition加载完成之后,实例化Bean对象之前提供修改BeanDefinition的机制
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
BeanReference
  • 这个类主要是应对这种情况
 <constructor-arg name="dog" ref="dog"></constructor-arg>
  • 这里面的属性依赖于某个类,通过BeanReference可以得到这个dog所对应的bean实例
ConfigurableBeanFactory
  • bean工厂的配置:比如销毁对象,实现对象的作用域啊,这些东西
SingletonBeanRegistry
  • 这个就是单例注册接口
public interface SingletonBeanRegistry {

    Object getSingleton(String beanName);

}
  • 以上就是bean工厂的配置信息

support文件夹

  • 做一些支持,就是实现下上面这些接口的方法
AbstractAutowireCapableBeanFactory
  • 这个类主要是创建Bean实例
AbstractBeanDefinitionReader
  • 这个类主要是实现BeanDefinitionReader的前两个方法,好让XmlBeanDefinitionReader这个类专注于xml文件解析和Bean注册逻辑的实现
AbstractBeanFactory
  • 抽象模板类
  • getBean的实现类
BeanDefinitionReader
  • 获取文件流,进而解析文件
BeanDefinitionRegistry
  • BeanDefinition的注册类
CglibSubclassingInstantiationStrategy
  • 动态代理创建有残构造器的Bean实例
DefaultListableBeanFactory
  • 最叼的类,实现了所有接口
  • 注册BeanDefinition的类
DefaultSingletonBeanRegistry
  • 注册单例的类
DisposableBeanAdapter
  • 销毁方法的适配器
InstantiationStrategy
  • 动态代理的类

xml文件夹

XmlBeanDefinitionReader
  • 解析xml文件,注册BeanDefinition

context

  • 上下文
  • 这里上文就是我们需要让spring管理的对象
  • 下文就是spring容器
  • 我是这么觉得的
  • 其中ApplicationContext就是衔接上下文的接口
    在这里插入图片描述
ApplicationContext
  • 衔接上下文的接口
ConfigurableApplicationContext
  • 继承了 ApplicationContext 实现 refresh() 方法
ClassPathXmlApplicationContext
  • 核心类

项目的实现过程

ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("bean5.xml");
  • 在这一步中
public ClassPathXmlApplicationContext(String[] configLocations) throws BeansException {
        this.configLocations = configLocations;
        refresh();
    }
  • 实现了refresh() 方法。(解析xml文件,并且注册BeanDefinition)
  • refresh() 是在 AbstractApplicationContext 中实现的
 public void refresh() throws BeansException {
        // 1. 创建 BeanFactory,并加载 BeanDefinition
        refreshBeanFactory();

        // 2. 获取 BeanFactory
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();

        // 3. 在 Bean 实例化之前,执行 BeanFactoryPostProcessor
        // (Invoke factory processors registered as beans in the context.)
        invokeBeanFactoryPostProcessors(beanFactory);

        // 4. BeanPostProcessor 需要提前于其他 Bean 对象实例化之前执行注册操作
        registerBeanPostProcessors(beanFactory);

        // 5. 提前实例化单例Bean对象
        beanFactory.preInstantiateSingletons();
    }
  • refreshBeanFactory(); 这个方法在AbstractRefreshableApplicationContext这个类中实现
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {

    private DefaultListableBeanFactory beanFactory;

    @Override
    protected void refreshBeanFactory() throws BeansException {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        loadBeanDefinitions(beanFactory);
        this.beanFactory = beanFactory;
    }

    private DefaultListableBeanFactory createBeanFactory() {
        return new DefaultListableBeanFactory();
    }

    protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory);

    @Override
    protected ConfigurableListableBeanFactory getBeanFactory() {
        return beanFactory;
    }

}
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext {

    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory,this);
        String[] configLocations = getConfigLocations();
        if (null != configLocations){
            beanDefinitionReader.loadBeanDefinitions(configLocations);
        }
    }

    protected abstract String[] getConfigLocations();

}
  • 这里面就是实现了xml文件的解析和BeanDefinition的注册(放到map里面去)
    在这里插入图片描述
  • 就是这个map
  • 要注意的是,解析的话,是全部都解析出来了,包括实现了BeanFactoryPostProcessor和BeanPostProcessor接口的类
  • 之后就是 invokeBeanFactoryPostProcessors(beanFactory);这个方法
  • 这个方法是在 Bean 实例化之前,执行 BeanFactoryPostProcessor
  • 因为到了这里,Bean还是只是个BeanDefinition,被注册在map里面
  • 只有执行getBean方法的时候才会实例化
private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
        for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()) {
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        }
    }
  • 这个方法就是,在上面截图的map里面把BeanFactoryPostProcessor.class这个类型的类全部拿出来,执行其postProcessBeanFactory方法
  • 之后就是执行registerBeanPostProcessors(beanFactory);这个方法,这个方法其实是注册BeanPostProcessor实现类的
  • 先把这些实现了BeanPostProcessor接口的类放到map里面去
    在这里插入图片描述
  • 就是上面这个map,因为这个已经扫描出来了,所以就放到AbstractBeanFactory里面了。
  • 等到getBean的时候,在执行其中重写的两个方法。
  • 最后就是beanFactory.preInstantiateSingletons();这个方法就是提前实例化单例对象
@Override
    public void preInstantiateSingletons() throws BeansException {
        beanDefinitionMap.keySet().forEach(this::getBean);
    }
  • 把map里面的BeanDefinition都拿出来,执行getBean方法。

部分类的继承关系

在这里插入图片描述

  • 这里可以看到,DefaultListableBeanFactory这个类实现了所有和bean工厂相关的接口
  • 这个是最屌的
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值