java|Spring-IoC注入过程
本文基于spring5.1.6
一、大体流程
- 使用ResourceLoader加载资源
- 创建Bean工厂
- 获得BeanDefinition
- 装载资源
资源定位、装载、注册
装载。装载就是 BeanDefinition 的载入
//加载资源
ClassPathResource resource = new ClassPathResource("bean.xml");
//创建bean工厂
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//xml解析器
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
//装载资源
reader.loadBeanDefinitions(resource);
不理解资源解析的请参考Spring-Resource源码解析
1.1 new XmlBeanDefinitionReader(factory)其实是调用的父类的构造方法
关系 public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader,EnvironmentCapable
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader
文章图片
1.2AbstractBeanDefinitionReader
- 创建对象就是初始化资源加载器和环境的过程
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
// 确定加载器如果BeanDefinitionRegistry是一个资源加载器,那么就使用它作为加载器,否则使用路径匹配加载器
if (this.registry instanceof ResourceLoader) {
this.resourceLoader = (ResourceLoader) this.registry;
}
else {
this.resourceLoader = new PathMatchingResourcePatternResolver();
} //EnvironmentCapable:Spring中所有的应用上下文类都实现了此接口。这个接口的主要作用是用于类型检查的
if (this.registry instanceof EnvironmentCapable) {
this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
}
else {
this.environment = new StandardEnvironment();
}
}
环境类Environment
/**
* 环境的一些参数
*/
public interface Environment extends PropertyResolver {
//获取激活的配置
String[] getActiveProfiles();
//默认的配置
String[] getDefaultProfiles();
//废弃的方法通过字符串的配置判断是否可以使用该配置
@Deprecated
boolean acceptsProfiles(String... profiles);
//通过Profiles对象判断是否可以使用该配置
boolean acceptsProfiles(Profiles profiles);
}public interface PropertyResolver { boolean containsProperty(String key);
//获取参数
@Nullable
String getProperty(String key);
//获取参数,如果为空,返回默认值
String getProperty(String key, String defaultValue);
//返回指定的对象的字节码对象
@Nullable
T getProperty(String key, Class targetType);
//返回指定的对象的字节码类,如果为空返回默认值
T getProperty(String key, Class targetType, T defaultValue);
//获取要求的参数
String getRequiredProperty(String key) throws IllegalStateException;
//获取要求的参数的对象的字节码对象
T getRequiredProperty(String key, Class targetType) throws IllegalStateException;
//解析占位符
String resolvePlaceholders(String text);
//解析要求的占位符
String resolveRequiredPlaceholders(String text) throws IllegalArgumentException;
}
1.3加载过程
loadBeanDefinitions会将资源进行编码,然后执行的是下面的代码
将encodedResource放入Set,去重
将encodedResource转成流并且将Resource对象传入doLoadBeanDefinitions,详见1.4源码
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);
}
//resourcesCurrentlyBeingLoaded是一个ThreadLocal对象
Set currentResources = this.resourcesCurrentlyBeingLoaded.get();
//如果是空的,那么就初始化一个set
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
//如果set集合添加不进去,那么抛出异常,说明已经加载过了,防止重复加载
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
//转换成流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
//设置编码
inputSource.setEncoding(encodedResource.getEncoding());
}
//见下方源码1.4
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
//ThreadLocal必须要remove掉,防止线程池下的线程复用
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
1.4doLoadBeanDefinitions方法
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException { try {
//获取Document 实例
Document doc = doLoadDocument(inputSource, resource);
//注册到ioc容器中详见1.5
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);
}
}
1.5 registerBeanDefinitions
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//利用反射创建对象详见1。6
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//registry是不是有点眼熟XmlBeanDefinitionReader extends AbstractBeanDefinitionReader
//在创建XmlBeanDefinitionReader的时候初始化了registry和environment
//也就是DefaultListableBeanFactory
//获取容器总数量
int countBefore = getRegistry().getBeanDefinitionCount();
//将Resource包装成XmlReaderContext详见1.7
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
//返回成功的个数beanDefinitionMap新增的数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
1.6 instantiateClass
public static T instantiateClass(Class clazz) throws BeanInstantiationException {
Assert.notNull(clazz, "Class must not be null");
//如果是接口,抛出异常
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
//如果不是接口,根据反射实例化对象
return instantiateClass(clazz.getDeclaredConstructor());
}
catch (NoSuchMethodException ex) {
Constructor ctor = findPrimaryConstructor(clazz);
if (ctor != null) {
return instantiateClass(ctor);
}
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
catch (LinkageError err) {
throw new BeanInstantiationException(clazz, "Unresolvable class definition", err);
}
}
1.7registerBeanDefinitions
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
//详见1.8
doRegisterBeanDefinitions(doc.getDocumentElement());
}
1.8doRegisterBeanDefinitions
@SuppressWarnings("deprecation")// for Environment.acceptsProfiles(String...)
protected void doRegisterBeanDefinitions(Element root) {
//解析器
BeanDefinitionParserDelegate parent = this.delegate;
//this.delegate重新指向新的delegate
this.delegate = createDelegate(getReaderContext(), root, parent);
//根节点是否为默认的命名空间,node.getNamespaceURI()为空
//或者为BeanDefinitionParserDelegate.BEANS_NAMESPACE_URI
//"http://www.springframework.org/schema/beans"
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
// 如果这个配置不合法
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
//什么都没做,需要子类来实现
preProcessXml(root);
//解析BeanDefinitions,详见1.9parseBeanDefinitions
parseBeanDefinitions(root, this.delegate);
//什么都没做,需要子类来实现
postProcessXml(root);
this.delegate = parent;
}
1.9parseBeanDefinitions
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//检测根节点是否使用默认的命名空间
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
//遍历节点
for (int i = 0;
i < nl.getLength();
i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
//处理默认的元素
parseDefaultElement(ele, delegate);
}
else {
//处理自定义的元素
delegate.parseCustomElement(ele);
}
}
}
}
else {
//处理自定义的元素
delegate.parseCustomElement(root);
}
}
2.0 parseDefaultElement处理默认的元素
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//import标签
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
//alias标签
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//bean标签
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
//2.2processBeanDefinition
processBeanDefinition(ele, delegate);
}
//beans标签
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
//调用1.9的方法继续往下解析即解析bean
doRegisterBeanDefinitions(ele);
}
}
2.1parseCustomElement处理客户自定义的元素
@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
2.2 processBeanDefinition
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//解析ele并且将bean封装到BeanDefinitionHolder
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
//如果不为空
if (bdHolder != null) {
//获取属性
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 注册到IOC容器
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
2.3parseBeanDefinitionElement 从xml中解析bean
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//获取id熟悉
String id = ele.getAttribute(ID_ATTRIBUTE);
//获取name熟悉
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
//将name属性值进行分割放入aliases中
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
//将id作为beanName,也就是说,id优先级最高
String beanName = id;
//id不存在的时候
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
//是否真的有值,把aliases的第一个元素放进来,那么把name作为beanname
beanName = aliases.remove(0);
if (logger.isTraceEnabled()) {
logger.trace("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
} if (containingBean == null) {
//检查是否唯一如果存在抛出异常,如果不存在那么缓存起来
checkNameUniqueness(beanName, aliases, ele);
}
//获取beanDefinition
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
//如果别名和id都为空的情况
if (!StringUtils.hasText(beanName)) {
try {
//如果不为空的情况下获取beanName
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
//根据上下文生成beanName
beanName = this.readerContext.generateBeanName(beanDefinition);
// 获取真正的java类名
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isTraceEnabled()) {
logger.trace("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
} return null;
}
2.4registerBeanDefinition
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException { // 获取bean名称
String beanName = definitionHolder.getBeanName();
//注册到IOC容器中
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
//注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
【java|Spring-IoC注入过程】2.5 registerBeanDefinition
@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");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
//通过Map查询是否存在BeanDefinition
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 + "]");
}
}
//如果不存在BeanDefinition
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
//注册进去IOC容器
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;
if (this.manualSingletonNames.contains(beanName)) {
Set> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
} if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
小结
1. 将Resource转成EncodedResource设置编码 2. 通过Resource和Resource的流获取Document 3. 通过命名空间(BEANS_NAMESPACE_URI = “http://www.springframework.org/schema/beans”; )判断是否是用户自定义的xml,然后解析不同的xml(我们这里只分析默认的) 4. 根据标签解析xml,spring解析import、alias、bean、beans 5. 解析bean标签、将Element对象封装成BeanDefinitionHolder 6. 将beanName作为key,BeanDefinition作为value保存到beanDefinitionMap中
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 事件代理
- 带有Hilt的Android上的依赖注入
- Java|Java OpenCV图像处理之SIFT角点检测详解
- 解决SpringBoot引用别的模块无法注入的问题
- java中如何实现重建二叉树
- 数组常用方法一
- 【Hadoop踩雷】Mac下安装Hadoop3以及Java版本问题
- Java|Java基础——数组
- RxJava|RxJava 在Android项目中的使用(一)