首页 > 代码库 > Spring技术内幕阅读笔记(一)

Spring技术内幕阅读笔记(一)

1.BeanFactory:实现ioc容器的最基本形式。
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String var1) throws BeansException;指定名字的bean

<T> T getBean(String var1, Class<T> var2) throws BeansException;

<T> T getBean(Class<T> var1) throws BeansException;byType

Object getBean(String var1, Object... var2) throws BeansException;

<T> T getBean(Class<T> var1, Object... var2) throws BeansException;

boolean containsBean(String var1);是否包含指定名字的bean

boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
是否为单例bean
boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
是否为原型bean
boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
查询指定名字的bean的class类型是否是特定的Class类型
boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
获取指定名字bean的Class类型
String[] getAliases(String var1);获取指定名字bean的所有别名
XmlBeanFactory:
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader;

public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, (BeanFactory)null);
}
BeanDefination来源在resource里,
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader = new XmlBeanDefinitionReader(this);
this.reader.loadBeanDefinitions(resource);
}
}
编程式使用Ioc容器
ClassPathResource res = new ClassPathResource("/applicationContext-core.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(res);
1.1Ioc容器的初始化是调用refresh()方法来启动的,
这个启动包括三个过程:1.BeanDefination的Resource定位2.载入3.注册
1).Resource定位:指的是BeanDefination的资源定位,寻找数据的过程。由ReaourceLoader通过统一的Resource接口来完成。
2).BeanDefination的载入。载入过程就是把用户定义好的Bean表示成Ioc容器内部的数据结构,而这个数据结构就是BeanDefination.
3).向Ioc容器注册这些BeanDefination的过程。这个过程是通过调用BeanDefinatinRegistry接口的实现来完成的。是把载入过程中的BeanDefination向Ioc容器进行注册,在Ioc容器内部将BeanDefination注入到一个HashMap里,Ioc容器就是通过这个HashMap持有这些BeanDefination数据。

载入和依赖注入区别:
依赖注入一般发生在应用第一次通过getBean向容器索取bean的时候,但是有一个例外就是可以对Bean设置lazyinit属性来完成bean的依赖注入,使其在初始化阶段就完成了。而不必要等到整个初始化完成以后,第一次getBean时才出发。
1.2 BeanDefiantion的Resource定位。
在ApplicationContext中Spring已经为我们提供了一系列加载不同Resource的读取器的实现,比如FileSystemXmlApplicationContext,ClassPathXmlApplicationContext,Xml
WebApplicationContext可以从文件系统,Class Path 或者web容器中载入Resource。

public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext {
public FileSystemXmlApplicationContext() {
}

public FileSystemXmlApplicationContext(ApplicationContext parent) {
super(parent);
}
//该构造函数的configLocation包含的是BeanDefination所在的文件路径
public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
this(new String[]{configLocation}, true, (ApplicationContext)null);
}
//该构造函数的configLocation包含多个BeanDefination所在的文件路径
public FileSystemXmlApplicationContext(String... configLocations) throws BeansException {
this(configLocations, true, (ApplicationContext)null);
}
//指定自己的双亲Ioc容器
public FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
this(configLocations, true, parent);
}

public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
this(configLocations, refresh, (ApplicationContext)null);
}
//调用refresh方法启动了BeanDefination的载入过程
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
this.setConfigLocations(configLocations);
if(refresh) {
this.refresh();
}

}

protected Resource getResourceByPath(String path) {
if(path != null && path.startsWith("/")) {
path = path.substring(1);
}

return new FileSystemResource(path);
}
}
1.3BeanDefination的载入和解析
载入过程:把定义的BeanDefination在Ioc容器中转换为一个Spring内部表示的数据结构的过程,这些BeanDefination数据在Ioc容器中通过一个HashMap来维护和保持。
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
this.setConfigLocations(configLocations);
//这里调用容器的refresh,是载入BeanDefination的入口
if(refresh) {
this.refresh();
}
}
容器的启动设计的很重要的方法refresh,在AbstractApplicationContext里,详细描述了ApplicationContext初始化的过程,比如BeanFactory的更新,MessageSource和PostProcessor的注册等等。
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
//设置BeanFactory的后置处理
this.postProcessBeanFactory(beanFactory);
//调用BeanFactory的后处理器
this.invokeBeanFactoryPostProcessors(beanFactory);
//注册Bean的后置处理器,在Bean创建过程中调用
this.registerBeanPostProcessors(beanFactory);
//对上下文的消息源进行初始化
this.initMessageSource();
//初始化上下文事件机制
this.initApplicationEventMulticaster();
//初始化其他的特殊Bean
this.onRefresh();
//检查监听Bean并且把这些Bean向容器注册
this.registerListeners();
//实例化所有的non-lazy-init的单件
this.finishBeanFactoryInitialization(beanFactory);
//发布容器时间,结束refresh过程
this.finishRefresh();
} catch (BeansException var9) {
if(this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
//为防止Baen资源占用,在异常处理中,销毁已经在前面生成的单件Bean
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
在refreshBeanFactory中,如果已经有容器存在则需要销毁和关闭。
不同形式的BeanDefination使用不同的BeanDefinationReader来完成数据的载入工作.
对于xml文件bean的property属性的解析,解析结果放到PropertyValue中,然后设置到BeanDefinationHolder中去。
1.4BeanDefination在Ioc容器中的注册
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
将解析得到的BeanDefination向Ioc容器的beanDefinationMap注册的过程是在载入BeanDefination完成后进行的。
首先DefaultListableBeanFactory实现了BeanDefinationRegistry接口,这个接口的实现完成了BeanDefination向容器的注册,注册过程不复杂,就是把BeanDefination设置到HashMap中去,需要注意的是,遇到同名的beanDefination需要允许覆盖。
注册BeanDefination过程
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
//获取beanName
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
String[] aliases = definitionHolder.getAliases();
if(aliases != null) {
String[] var4 = aliases;
int var5 = aliases.length;
//
for(int var6 = 0; var6 < var5; ++var6) {
String alias = var4[var6];
registry.registerAlias(beanName, alias);
}
}

}

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");
if(beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var9) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var9);
}
}
BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if(oldBeanDefinition != null) {
if(!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean ‘" + beanName + "‘: There is already [" + oldBeanDefinition + "] bound.");
}
if(oldBeanDefinition.getRole() < beanDefinition.getRole()) {
if(this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean ‘" + beanName + "‘ with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if(!beanDefinition.equals(oldBeanDefinition)) {
if(this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean ‘" + beanName + "‘ with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if(this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean ‘" + beanName + "‘ with an equivalent definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
if(this.hasBeanCreationStarted()) {
Map var4 = this.beanDefinitionMap;
synchronized(this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if(this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
} else {
//注册BeanDefination的过程,把beanName存到beanDefinitionNames的同时,把beanName作为Map的key,把BeanDefination做为value存到BeanDefinationMap中
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if(oldBeanDefinition != null || this.containsSingleton(beanName)) {
this.resetBeanDefinition(beanName);
}

Spring技术内幕阅读笔记(一)