Spring源码的核心就是工厂 也是我们常说的容器。
而ApplicationContext是高级工厂 类似于mybatis的sqlSession。
了解Spring的源码 需要首先弄清楚BeanFactory和FactoryBean有什么区别?
BeanFactory是个Factory,也就是Ico容器或者是对象工厂,而FactoryBean就是个Bean。 在Spring中,所有的bean都是由BeanFactory(IOC容器)来进行管理的。但是对于FactoryBean而言,这个bean不是个简单的bean,而是一个能生产或者修饰对象生成的工厂bean。
1.BeanFactory
BeanFactory定义了IOC容器的最基本形式, 并且提供了IOC容器应该遵守的最基本的接口,也就是Spring IOC所遵守的最底层和最基本的编程规范。在Spring源码中,BeanFacotry只是个接口,并不是IOC容器的具体实现,但是spring容器给除了很多种实现,例如:DefaultListbaBeanFactory,XmlBeanFactory,ApplicatonContext等,都是附加了某种功能的实现。
BeanFaoctry接口:
基本操作:
package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
T getBean(String name, Class requiredType) throws BeansException;
T getBean(Class requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException;
Class getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
BeanFacotry的结构:
BeanFactory: 共有四个实现(三个接口,一个实现)
1.HierarchicalBeanFactory
2.SimpleJndiBeanFactory(一般不用)
3.AutowireCapableBeanFactory
4.ListablBeanFactory
对于BeanFacgtory在最终的实现类中, 大部分都是由DefaultListableBeanFactory,所以说这个DefaultListableBeanFacotry包含了大部分BeanFacotry的功能,是个大成者。
HierarchicalBeanFactory:有个两个实现接口:
1.ConfigurableBeanFactory
可配置工厂: 单实例、多实例的scope类型、 类型转换、后置处理bean等
2.ApplicatonContext
AutowireCapabelBeanFactory: 具有InitialBean、 DisposeBean等作用
ListableBeanFactory: 获取bena的相关配置信息
而对于DefaultListablBeanFactory来说 符合上述大部分工厂的接口实现
XmlBeanFactory继承于DefaultListbaleBeanFacotry的一个实现,作用是读取xml的配置信息,完成对象的创建。核心是依靠于XMLBeanDefinitionReader这个类。
ApplicatonContext 是集工厂功能大成的类型编程,面向开发
代码实现:
@Test
public void test1(){
//过时写法
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
User u = (User)beanFactory.getBean("u");
System.out.println("u = " + u);
//DefaultListablBeanFactory 是beanfactory的大成者 包含了大部分BeanFactory的功能
DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
reader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
User user = defaultListableBeanFactory.getBean("u", User.class);
System.out.println("user = " + user);
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User appUser = (User)applicationContext.getBean("u");
System.out.println("appUser = " + appUser);
}
最终都会打印:
11:49:51.150 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 1 bean definitions from class path resource [applicationContext.xml]
11:49:51.157 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanFactory - Creating shared instance of singleton bean 'u'
u = User{id=10, name='zhangsan'}
11:49:51.361 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 1 bean definitions from class path resource [applicationContext.xml]
11:49:51.362 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'u'
user = User{id=10, name='zhangsan'}
11:49:51.387 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@177bea38
11:49:51.488 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 1 bean definitions from class path resource [applicationContext.xml]
11:49:51.558 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'u'
appUser = User{id=10, name='zhangsan'}
2.FactoryBean
Spring创建的对象有两种,一个是简单对象,另外一个是复杂对象(FactoryBean)
一般情况下,spring 通过反射机制利用bean的class属性指定实现类实例化Bean,在某些i情况下,实例化bena过程比较复杂,如果按照传统的方式, 则许哟啊在bean提供大量的配置信息。配置方式的灵活比较受限,spring提供了一个org.springframword.bean.factory.FactoryBean的工厂接口,用户可以通过实现这个接口定制实例化bean的逻辑。
FactoryBean接口对于spring框架来说占有比较重要地位。spring提供了70多种FactoryBean的实现,他们隐藏了一下复杂bean的细节,给上层带来了便利。从spring3.0来时,FactoryBean开始支持泛型,即接口声明改成了FactoryBean
package org.springframework.beans.factory;
public interface FactoryBean {
T getObject() throws Exception;
Class getObjectType();
boolean isSingleton();
}
当调用一个类实现FactoryBean的时候,getBean(),spring通过反射机制发现了实现了FactoryBean的接口,这时spring容器就会调用接口方法的getObject方法。如果想要获取实现FactoryBean的类实现对象,则需要在使用getBean()方法的时候 在beanName上加&前缀。
分析:
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) ctx.getBean("u");
在读取配置文件的过程汇总,主要发生了什么?
以XmlBeanFactory为例:
1. 读取XML配置文件,XML配置文件 封装 Java对象 ---> 创建工厂生产的对象
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
2. 从工厂容器中获得对象
User user = (User) beanFactory.getBean("u");
过程读取:
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
首先
XmlBeanFactory 继承了DefaultListbaleBeanFactory接口, 在XmlBeanFactory实现类中,定义了一个XmlBeanDefinitionReader 对象,这个对象的作用就是为了读取xml配置文件,通过对象调用Resource顶级接口,在创建XmlBeanFacotry中,我们创建一个了ClassPathResource对象,传入了文件路径。
对于Resource接口来说,不仅能都读取磁盘中的 .xml .properties .txt等文件,还可以读取网络中的文件。实现Resource接口,有很多的实现类,例如:ClassPathResource. FileSystemResource, ByteArrayResource等
如图:
通过XmlBeanDefinitonReader来读取文件
InputSource是解析xml的一种方式
XML解析
mybatis xml解析 xpath
spring xml解析 SAX
通过前置获取的BeanDefinitonDocumentReader对象调用其接口提供的方法:
DefaultBeanDefintionDocumentReader实现了BeanDefinitionDocumentReader接口,重写了其接口方法
其中Element入参是前置传入document对象的属性 目的是通过元素 加载beandefintion的对象
BeanDefintionHolder类: