一、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 + "打起来了");
}
public static void main(String[] args) {
Dog dog = new Dog("Jim");
Cat cat = new Cat(dog,"Tom");
cat.fight();
}
}
<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 {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
destroyBeans();
cancelRefresh(ex);
throw ex;
}
finally {
resetCommonCaches();
}
}
}
自研Spring框架
- 这个项目其实大体上很容易理解,就是将xml解析出来的内容交给自己研发出来的spring框架去处理,为了是代码的质量更高一点,所以应用了很多的设计模式,使不同的接口或者抽象类实现不同的功能。
Xml解析
- 这个很简单就是通过xml文件的路径,获得Document,然后进行解析
Bean
- Bean在我看来其实就是源码里面的BeanDefinition
- 以下是我定义的BeanDefinition
public class BeanDefinition {
private Class beanClass;
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;
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
}
DisposableBean
public interface DisposableBean {
void destroy() throws Exception;
}
HierarchicalBeanFactory
InitializingBean
ListableBeanFactory
public interface ListableBeanFactory extends BeanFactory{
<T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
String[] getBeanDefinitionNames();
}
config文件夹
AutowireCapableBeanFactory(自动装配)
- 这里面实现的就是BeanPostProcessors中的两个方法
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException;
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException;
BeanDefinition
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);
}
support文件夹
AbstractAutowireCapableBeanFactory
AbstractBeanDefinitionReader
- 这个类主要是实现BeanDefinitionReader的前两个方法,好让XmlBeanDefinitionReader这个类专注于xml文件解析和Bean注册逻辑的实现
AbstractBeanFactory
BeanDefinitionReader
BeanDefinitionRegistry
CglibSubclassingInstantiationStrategy
DefaultListableBeanFactory
- 最叼的类,实现了所有接口
- 注册BeanDefinition的类
DefaultSingletonBeanRegistry
DisposableBeanAdapter
InstantiationStrategy
xml文件夹
XmlBeanDefinitionReader
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 {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
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工厂相关的接口
- 这个是最屌的