这4级接口是BeanFactory的基本接口体系。继续,下面是继承关系的2个抽象类和2个实现类:
spring访问资源的方式有了,那么spring是怎么加载资源的呢?下面我们来看ResourceLoader模块。
如果说BeanFactory是Spring的心脏,那么ApplicationContext就是完整的躯体了,ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能。在BeanFactory中,很多功能需要以编程的方式实现,而在ApplicationContext中则可以通过配置实现。
如下UML:
有了加载器ResourceLoader,也拥有了对资源的描述Resource,也有了对自动股票交易系统接口,bean的定义,我们不禁要问,我们的Resource资源是怎么转成我们的BeanDefinition的呢?因此就引入了BeanDefinitionReader。
ApplicationContext:是IOC容器另一个重要接口,它继承了BeanFactory的基本功能,同时也继承了容器的高级功能,如:MessageSource、ResourceLoader、ApplicationEventPublisher等。
BeanFactory接口
Resource接口本身没有提供访问任何底层资源的实现逻辑,针对不同的底层资源,Spring将会提供不同的Resource实现类,不同的实现类负责不同的资源访问逻辑,每个实现类代表一种资源访问策略。
既然我们拥有了加载器ResourceLoader,也拥有了对资源的描述Resource,但是我们在xml文件中声明的标签在Spring又是怎么表示的呢?注意这里只是说对自动股票交易系统接口,bean的定义,而不是说如何将转换为自动股票交易系统接口,bean对象。于是就引入一个叫BeanDefinition的组件。
XmlBeanFactory通过Resource装载Spring配置信息冰启动IoC容器,然后就可以通过factory.getBean从IoC容器中获取Bean了。通过BeanFactory启动IoC容器时,并不会初始化配置文件中定义的Bean,初始化动作发生在第一个调用时。对于单实例的Bean来说,BeanFactory会缓存Bean实例,所以第二次使用getBean时直接从IoC容器缓存中获取Bean。
BeanFactorty接口提供了配置框架及基本功能,但是无法支持spring的aop功能和web应用。而ApplicationContext接口作为BeanFactory的派生,因而提供BeanFactory所有的功能。而且ApplicationContext还在功能上做了扩展,相较于BeanFactorty,ApplicationContext还提供了以下的功能:
该组件负责对Spring资源的加载,资源指的是xml、properties等文件资源,返回一个对应类型的Resource对象。
/*
* 定义资源加载器,主要应用于根据给定的资源文件地址返回对应的Resource
*/
public interface ResourceLoader {
Resource getResource(String location);
@Nullable
ClassLoader getClassLoader();
}
接下来我们来看一下ResourceLoader具体的实现类有哪些:从上面的UML可以看出,ResourceLoader组件其实跟Resource组件差不多,都是一个根接口,对应有不同的子类实现,比如加载来自文件系统的资源,则可以使用FileSystemResourceLoader,加载来自ServletContext上下文的资源,则可以使用ServletContextResourceLoader。还有最重要的一点,从上看出,ApplicationContext,AbstractApplication是实现了ResourceLoader的,这说明什么呢?说明我们的应用上下文ApplicationContext拥有加载资源的能力,这也说明了为什么可以通过传入一个Stringresourcepath给ClassPathXmlApplicationContext(“applicationContext.xml”)就能获得xml文件资源的原因了!
BeanDefinition是一个接口,内部定义了自动股票交易系统接口,bean对象的一些基本行为。配置文件中的标签跟我们的BeanDefinition是一一对应的,元素标签拥有class、scope、lazy-init等配置属性,BeanDefinition则提供了相应的自动股票交易系统接口,beanClass、scope、lazyInit属性。
有了BeanDefinition后,你还必须将它们注册到工厂中去,所以当你使用getBean()方法时工厂才知道返回什么给你。BeanDefinitionRegistry出场。
UrlResource:访问网络资源的实现类。ClassPathResource:访问类加载路径里资源的实现类。FileSystemResource:访问文件系统里资源的实现类。ServletContextResource:访问相对于ServletContext路径里的资源的实现类。InputStreamResource:访问输入流资源的实现类。ByteArrayResource:访问字节数组资源的实现类。
BeanFactory最常见的实现类为XmlBeanFactory,可以从classpath或文件系统等获取资源。
Spring通过BeanDefinition将配置文件中的配置信息转换为容器的内部表示,并将这些BeanDefiniton注册到BeanDefinitonRegistry中。Spring容器的BeanDefinitionRegistry就像是Spring配置信息的内存数据库,主要是以map的形式保存,后续操作直接从BeanDefinitionRegistry中读取配置信息。一般情况下,BeanDefinition只在容器启动时加载并解析,除非容器刷新或重启,这些信息不会发生变化,当然如果用户有特殊的需求,也可以通过编程的方式在运行期调整BeanDefinition的定义。
BeanFactory作为一个主接口不继承任何接口,暂且称为一级接口。有3个子接口继承了它,进行功能上的增强。这3个子接口称为二级接口。ConfigurableBeanFactory可以被称为三级接口,对二级接口HierarchicalBeanFactory进行了再次增强,它还继承了另一个外来的接口SingletonBeanRegistry。ConfigurableListableBeanFactory是一个更强大的接口,继承了上述的所有接口,无所不包,称为四级接口。
BeanFactory是Spring的“心脏”。它就是SpringIoC容器的真面目。Spring使用BeanFactory来实例化、配置和管理Bean。BeanFactory:是IOC容器的核心接口,它定义了IOC的基本功能,我们看到它主要定义了getBean方法。getBean方法是IOC容器获取自动股票交易系统接口,bean对象和引发依赖注入的起点。方法的功能是返回特定的名称的Bean。BeanFactory是初始化Bean和调用它们生命周期方法的“吃苦耐劳者”。注意,BeanFactory只能管理单例Bean的生命周期。它不能管理原型(prototype,非单例)Bean的生命周期。这是因为原型Bean实例被创建之后便被传给了客户端,容器失去了对它们的引用。BeanFactory有着庞大的继承、实现体系,有众多的子接口、实现类。来看一下BeanFactory的基本类体系结构:
ApplicationContext的子接口分为两个部分:
AbstractBeanFactory作为一个抽象类,实现了三级接口ConfigurableBeanFactory大部分功能。AbstractAutowireCapableBeanFactory同样是抽象类,继承自AbstractBeanFactory,并额外实现了二级接口AutowireCapableBeanFactory。DefaultListableBeanFactory继承自AbstractAutowireCapableBeanFactory,实现了最强大的四级接口ConfigurableListableBeanFactory,并实现了一个外来接口BeanDefinitionRegistry,它并非抽象类。最后是最强大的XmlBeanFactory,继承自DefaultListableBeanFactory,重写了一些功能,使自己更强大。
package org.springframework.自动股票交易系统接口,beans.factory;
public interface BeanFactory {
/**
* 用来引用一个实例,或把它和工厂产生的Bean区分开,就是说,如果一个FactoryBean的名字为a,那么,&a会得到那个Factory
*/
String FACTORY_BEAN_PREFIX = '&';
/*
* 四个不同形式的getBean方法,获取实例
*/
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);// 根据实例的名字获取实例的别名
我们以XmlBeanDefinitionReader为例:
/**
* 创建XmlBeanDefinitionReader需要传入一个BeanDefinitionRegistry实例
*/
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
super(registry);
}
/**
* XmlBeanDefinitionReader加载资源的入口方法
*/
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
// 将读入的XML资源进行特殊编码处理
return loadBeanDefinitions(new EncodedResource(resource));
}
/**
* 载入XML形式Bean配置信息方法
*/
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, 'EncodedResource must not be null');
if (logger.isTraceEnabled()) {
logger.trace('Loading XML 自动股票交易系统接口,bean definitions from ' + encodedResource);
}
Set currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
'Detected cyclic loading of ' + encodedResource + ' - check your import definitions!');
}
try {
// 将资源文件转为InputStream的IO流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
// 从InputStream中得到XML的解析源
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 具体读取过程
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
// 关闭从Resource中得到的IO流
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
'IOException parsing XML document from ' + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
/**
* 从特定XML文件中实际载入Bean配置资源的方法
*/
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 将XML文件转换为DOM对象,解析过程由documentLoader方法实现
Document doc = doLoadDocument(inputSource, resource);
// 启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean配置规则
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug('Loaded ' + count + ' 自动股票交易系统接口,bean definitions from ' + resource);
}
return count;
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
'Line ' + ex.getLineNumber() + ' in XML document from ' + resource + ' is invalid', ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
'XML document from ' + resource + ' is invalid', ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
'Parser configuration exception parsing XML from ' + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
'IOException parsing XML document from ' + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
'Unexpected exception parsing XML document from ' + resource, ex);
}
}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//得到BeanDefinitionDocumentReader来对XML格式的BeanDefinition进行解析
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//获取容器中注册的Bean数量
int countBefore = getRegistry().getBeanDefinitionCount();
//加载及注册自动股票交易系统接口,bean,具体的解析过程由实现类DefaultBeanDefinitionDocumentReader完成
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
//记录本次加载的BeanDefinition个数
return getRegistry().getBeanDefinitionCount() - countBefore;
}
MessageSource,提供国际化的消息访问资源访问,如URL和文件事件传播特性,即支持aop特性载入多个上下文,使得每一个上下文都专注于一个特定的层次,比如应用的web层
Spring为资源访问提供了一个Resource接口,该接口提供了更强的资源访问能力,Spring框架本身大量使用了Resource接口来访问底层资源。
ResourceLoader接口
BeanDefinitionReader作用是把Resource资源转成我们的BeanDefinition。从上面可以看出,Spring对reader进行了抽象,具体的功能交给其子类去实现,不同的实现对应不同的类,如PropertiedBeanDefinitionReader,XmlBeanDefinitionReader对应从Property和xml的Resource解析成BeanDefinition。
AbstractApplicationContext是ApplicationContext接口的抽象实现,这个抽象类仅仅是实现了公共的上下文特性。这个抽象类使用了模板方法设计模式,需要具体的实现类去实现这些抽象的方法。
Resource接口
BeanDefinition接口部分方法:BeanDefinitionUML其中RootBeanDefinition是最常用的实现类,它对应一般性的元素标签。GenericBeanDefinition是自5以后新加入的自动股票交易系统接口,bean文件配置属性定义类,是一站式服务类。在配置文件中可以定义父和子类,父用RootBeanDefinition表示,而子用ChildBeanDefiniton表示,而没有父的话就使用RootBeanDefinition表示。AbstractBeanDefinition对两者共同的类信息进行抽象。
通过XmlBeanFactory实现启动SpringIoC容器:
public class MyTest {
@Test
public void test01() throws FileNotFoundException {
// ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext('application_context.xml');
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource resource=resolver.getResource('classpath:application_context.xml');
BeanFactory 自动股票交易系统接口,beanFactory=new XmlBeanFactory(resource);
BookService bookService = 自动股票交易系统接口,beanFactory.getBean('bookService', BookService.class);
System.out.println(bookService);
}
}
BeanDefinition接口
BeanDefinitionRegistry接口UML:从中可以看出,BeanDefinitionRegistry有三个默认实现,分别是SimpleBeanDefinitionRegistry,DefaultListableBeanFactory,GenericApplicationContext,其中SimpleBeanDefinitionRegistry,DefaultListableBeanFactory都持有一个Map,也就是说这两个实现类把保存了自动股票交易系统接口,bean。而GenericApplicationContext则持有一个DefaultListableBeanFactory对象引用用于获取里边对应的Map。
/*
1. 整个自动股票交易系统接口,bean加载的核心部分,是spring注册及加载自动股票交易系统接口,bean的默认实现
*/
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
//存储注册信息的BeanDefinition
private final Map 自动股票交易系统接口,beanDefinitionMap = new ConcurrentHashMap<>(256);
//向Spring IOC容器注册解析的BeanDefinition
@Override
public void registerBeanDefinition(String 自动股票交易系统接口,beanName, BeanDefinition 自动股票交易系统接口,beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(自动股票交易系统接口,beanName, 'Bean name must not be empty');
Assert.notNull(自动股票交易系统接口,beanDefinition, 'BeanDefinition must not be null');
//检验解析的BeanDefinition
if (自动股票交易系统接口,beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) 自动股票交易系统接口,beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(自动股票交易系统接口,beanDefinition.getResourceDescription(), 自动股票交易系统接口,beanName,
'Validation of 自动股票交易系统接口,bean definition failed', ex);
}
}
BeanDefinition existingDefinition = this.自动股票交易系统接口,beanDefinitionMap.get(自动股票交易系统接口,beanName);
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(自动股票交易系统接口,beanName, 自动股票交易系统接口,beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < 自动股票交易系统接口,beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info('Overriding user-defined 自动股票交易系统接口,bean definition for 自动股票交易系统接口,bean '' + 自动股票交易系统接口,beanName +
'' with a framework-generated 自动股票交易系统接口,bean definition: replacing [' +
existingDefinition + '] with [' + 自动股票交易系统接口,beanDefinition + ']');
}
}
else if (!自动股票交易系统接口,beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug('Overriding 自动股票交易系统接口,bean definition for 自动股票交易系统接口,bean '' + 自动股票交易系统接口,beanName +
'' with a different definition: replacing [' + existingDefinition +
'] with [' + 自动股票交易系统接口,beanDefinition + ']');
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace('Overriding 自动股票交易系统接口,bean definition for 自动股票交易系统接口,bean '' + 自动股票交易系统接口,beanName +
'' with an equivalent definition: replacing [' + existingDefinition +
'] with [' + 自动股票交易系统接口,beanDefinition + ']');
}
}
this.自动股票交易系统接口,beanDefinitionMap.put(自动股票交易系统接口,beanName, 自动股票交易系统接口,beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
//注册的过程中需要线程同步,以保证数据的一致性
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.自动股票交易系统接口,beanDefinitionMap) {
this.自动股票交易系统接口,beanDefinitionMap.put(自动股票交易系统接口,beanName, 自动股票交易系统接口,beanDefinition);
List updatedDefinitions = new ArrayList<>(this.自动股票交易系统接口,beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.自动股票交易系统接口,beanDefinitionNames);
updatedDefinitions.add(自动股票交易系统接口,beanName);
this.自动股票交易系统接口,beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(自动股票交易系统接口,beanName);
}
}
else {
// Still in startup registration phase
this.自动股票交易系统接口,beanDefinitionMap.put(自动股票交易系统接口,beanName, 自动股票交易系统接口,beanDefinition);
this.自动股票交易系统接口,beanDefinitionNames.add(自动股票交易系统接口,beanName);
removeManualSingletonName(自动股票交易系统接口,beanName);
}
this.frozenBeanDefinitionNames = null;
}
//检查是否已经注册过同名的BeanDefinition
if (existingDefinition != null || containsSingleton(自动股票交易系统接口,beanName)) {
//重置所有已经注册过的BeanDefinition的缓存
resetBeanDefinition(自动股票交易系统接口,beanName);
}
}
}
文章为作者独立观点,不代表股票交易接口观点