开始剖析了好紧张啊,Spring还是写个半懂就开始剖析了
先从ioc开始分析,因为我也不太会所以从最基础的来
分析的版本为3.2.x
因为比较稳定,而且也是主流的版本,从github上就能下到,然后使用的是sourceinsght
不用图片说话自己就会忘记
AliasRegistry:定义对alias的简单增删改
Single
ListableBeanFactory根据条件获取bean的配置清单。
AbstractBeanFactory 提供了Register支持和Configable的
先理解下几个问题
1.Spring存放了类的哪些信息呢?
①类名(姓名),该类是否抽象(种别),该类的父类(家庭信息),该类的包名(家庭地址)(基本信息)
②属性,构造函数(否则怎么构造函数注入和Setter注入啊?)
③Annotation(否则你@Controller写这样的注解的时候,它怎么知道他是Controller呢?)
这些信息就是类的名片,根据这些信息,我们容器就可以把该类“造”出来,BeanDefinition
其次就是BeanFactory ioc中 最重要的接口
先分析BeanFactory 刚开始带着翻译讲,而且有利于提高英语阅读能力,后面的话只看比较重要的部分
package org.springframework.beans.factory;
* The root interface for accessing a Spring bean container.
* This is the basic client view of a bean container;
原话:这是一个spring容器的根接口,展现给使用者
进一步的更专用接口有ListableBeanFactory和ConfigurableBeanFactory
* <p>This interface is implemented by objects that hold a number of bean definitions,
* each uniquely identified by a String name. Depending on the bean definition,
* the factory will return either an independent instance of a contained object
* (the Prototype design pattern), or a single shared instance (a superior
* alternative to the Singleton design pattern, in which the instance is a
* singleton in the scope of the factory)
差不多是讲这个接口被持有具体bean定义的目标对象实例化并且通过id区分,工厂可以返回一个单例的(默认)或者原型的实例
* <p>Note that it is generally better to rely on Dependency Injection
* ("push" configuration) to configure application objects through setters
* or constructors, rather than use any form of "pull" configuration like a
* BeanFactory lookup. Spring's Dependency Injection functionality is
* implemented using this BeanFactory interface and its subinterfaces.
依赖注入的设置注入和构造注入更优于 传统的pull ,Spring的di是通过BeanFactory和子类实现
* <p>Normally a BeanFactory will load bean definitions stored in a configuration
* source (such as an XML document), and use the {@code org.springframework.beans}
* package to configure the beans. However, an implementation could simply return
* Java objects it creates as necessary directly in Java code. There are no
* constraints on how the definitions could be stored: LDAP, RDBMS, XML,
* properties file, etc. Implementations are encouraged to support references
* amongst beans (Dependency Injection).
BeanFactory通常从xml配置文件中加载bean定义
The full set of initialization methods and their standard order is:<br>
* 1. BeanNameAware's {@code setBeanName}<br>
* 2. BeanClassLoaderAware's {@code setBeanClassLoader}<br>
* 3. BeanFactoryAware's {@code setBeanFactory}<br>
* 4. EnvironmentAware's {@code setEnvironment}
* 5. EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
* 6. ResourceLoaderAware's {@code setResourceLoader}
* (only applicable when running in an application context)<br>
* 7. ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
* (only applicable when running in an application context)<br>
* 8. MessageSourceAware's {@code setMessageSource}
* (only applicable when running in an application context)<br>
* 9. ApplicationContextAware's {@code setApplicationContext}
* (only applicable when running in an application context)<br>
* 10. ServletContextAware's {@code setServletContext}
* (only applicable when running in a web application context)<br>
* 11. {@code postProcessBeforeInitialization} methods of BeanPostProcessors<br>
* 12. InitializingBean's {@code afterPropertiesSet}<br>
* 13. a custom init-method definition<br>
* 14. {@code postProcessAfterInitialization} methods of BeanPostProcessors
设置注入的完整流程
* <p>On shutdown of a bean factory, the following lifecycle methods apply:<br>
* 1. {@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
* 2. DisposableBean's {@code destroy}<br>
* 3. a custom destroy-method definition
关闭后的流程
这个接口其实很简单 也没啥讲的 主要是获取实例和判断类型,给bean起别名
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> 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;
boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
所以BeanFactory只是定义了“汤勺”的基本性质,我们来看看他的子类,看看具体的一些汤勺吧~
DefaultListableBeanFactory最牛比的一个类
先看源码定义
* Default implementation of the
* {@link org.springframework.beans.factory.ListableBeanFactory} and
* {@link BeanDefinitionRegistry} interfaces: a full-fledged bean factory
* based on bean definition objects.
*
* <p>Typical usage is registering all bean definitions first (possibly read
* from a bean definition file), before accessing beans. Bean definition lookup
* is therefore an inexpensive operation in a local bean definition table,
* operating on pre-built bean definition metadata objects.
*
* <p>Can be used as a standalone bean factory, or as a superclass for custom
* bean factories. Note that readers for specific bean definition formats are
* typically implemented separately rather than as bean factory subclasses:
* see for example {@link PropertiesBeanDefinitionReader} and
* {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}.
*
* <p>For an alternative implementation of the
* {@link org.springframework.beans.factory.ListableBeanFactory} interface,
* have a look at {@link StaticListableBeanFactory}, which manages existing
* bean instances rather than creating new ones based on bean definitions.
差不多是讲这是它们的默认实现,源码讲的像屎一样,这里就不翻译了
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
挑重要的讲吧 主要对bean注册后的处理
ConfigurableListableBeanFactory BeanFactory配置清单,指定忽略类型和接口
该类拥有的属性有
serializationId 序列号id
allowBeanDefinitionOverriding = true 是否可 以 重名
allowEagerClassLoading = true 是否延迟加
/** Map from serialized id to factory instance */
private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
new ConcurrentHashMap<String, Reference<DefaultListableBeanFactory>>(8);
AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver()
final Map<Class<?>, Object> resolvableDependencies = new HashMap<Class<?>, Object>(16);
final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
final List<String> beanDefinitionNames = new ArrayList<String>(64);
boolean configurationFrozen = false;
String[] frozenBeanDefinitionNames;
构造方法有多种,基本以父类构造为主
public DefaultListableBeanFactory() {
super();
}
接口实现
//---------------------------------------------------------------------
// Implementation of ListableBeanFactory interface
//---------------------------------------------------------------------
public <T> T getBean(Class<T> requiredType) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
//获取beanname数组
String[] beanNames = getBeanNamesForType(requiredType);
if (beanNames.length > 1) {
ArrayList<String> autowireCandidates = new ArrayList<String>();
for (String beanName : beanNames) {
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
autowireCandidates.add(beanName);
}
}
if (autowireCandidates.size() > 0) {
beanNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
}
}
if (beanNames.length == 1) {
return getBean(beanNames[0], requiredType);//父类方法
}
else if (beanNames.length > 1) {
T primaryBean = null;
for (String beanName : beanNames) {
T beanInstance = getBean(beanName, requiredType);
if (isPrimary(beanName, beanInstance)) {
if (primaryBean != null) {
throw new NoUniqueBeanDefinitionException(requiredType, beanNames.length,
"more than one 'primary' bean found of required type: " + Arrays.asList(beanNames));
}
primaryBean = beanInstance;
}
}
if (primaryBean != null) {
return primaryBean;
}
throw new NoUniqueBeanDefinitionException(requiredType, beanNames);
}
else if (getParentBeanFactory() != null) {
return getParentBeanFactory().getBean(requiredType);
}
else {
throw new NoSuchBeanDefinitionException(requiredType);
}
}
我们在来看父类
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
看到实例缓存
private final Map<String, BeanWrapper> factoryBeanInstanceCache =
new ConcurrentHashMap<String, BeanWrapper>(16);
构造函数
public AbstractAutowireCapableBeanFactory() {
super();
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
}
它的子类
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
}
补充:
容器的基础xmlBeanFactory
主要从xml文档中读取BeanDefinition 注册和获取Bean都是父类DefaultListableBeanFactory继承的方法去实现
不同点多了XmlBeanDefinitionReader reader对资源文件 进行读取和注册
XmlBeanDefinitionReader分析
我们然后梳理资源文件读取解析注册的大致脉络
ResourceLoader 定义资源加载类返回Resource
BeanDefinationReader 定义资源文件转换为BeanDefitionReader的各个功能
EnirmentCapable 定义获取Environment方法
DoucumentLoader定义从资源文件加载转化到Doucment的功能
AbstractBeanDefinationReader对以上实现
BeanDefinationDocumentReader定义读取Dcument并注册BeanDefination功能
BeanDefiantionPaserDelegate定义解析Element方法
xml读取的大致流程
1.继承AbstractBeanDefinationReader 中的方法来使用ResourceLoader将资源路径转化为Resource文件
2.通过DoucumentLoader把Resource转化为Document文件
3.通过DefaultBeanDefinitionDoucmentReader类对Doucment解析,并使用BeanDefinitionParserDelegate对Element解析
通常通过ClassPathResource来构造Resource资源实例供后续处理,那么Resource资源如何封装的呢??
配置文件的封装
Resource接口来实现底层资源的封装 InputStreamSource 只有一个getInputStream() 方法
public interface Resource extends InputStreamSource {
先分析ClassPathResource
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
boolean exists();
boolean isReadable();
boolean isOpen();
URL getURL() throws IOException;
URI getURI() throws IOException;
File getFile() throws IOException;
long contentLength() throws IOException;
long lastModified() throws IOException;
Resource createRelative(String relativePath) throws IOException;
String getFilename();
String getDescription();//错误处理中打印信息
}
感觉相当于对url补充,提供了检查当前资源状态(可读,存在,打开)的接口
Resource接口抽象了Spring内部使用到的底层资源File,URL,URI,Classpath,以及获取权限或者文件名的方法
createRealative()提供创建一个相对资源的方法