前面的博客我们已经介绍完了spring的依赖的查找和注入的方式,这篇博客我们主要介绍下spring的依赖的查找和注入的来源。
查找来源
Spring 內建 BeanDefintion
Spring 內建单例对象
上面的各种依赖都是在spring的生命周期的过程中,初始化的,这儿不做过多的赘述,后面的博客我们在详细的介绍。
注入来源
具体的代码如下:
package org.learn.spring.dependency.source;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.io.ResourceLoader;
import javax.annotation.PostConstruct;
// 依赖来源示例
// BeanFactory.class ResourceLoader.class ApplicationEventPublisher.class ApplicationContext.class 不能用于我们的getBean
public class DependencySourceDemo {
// 注入在 postProcessProperties 方法执行,早于 setter注入 也早于生命周期回调函数@PostConstruct
@Autowired
private BeanFactory beanFactory;
@Autowired
private ResourceLoader resourceLoader;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Autowired
private ApplicationContext applicationContext;
@PostConstruct
public void init() {
System.out.println("beanFactory == applicationContext :" + (beanFactory == applicationContext));
System.out.println("beanFactory == applicationContext.getAutowireCapableBeanFactory() :" + (beanFactory == applicationContext.getAutowireCapableBeanFactory()));
System.out.println("resourceLoader == applicationContext :" + (resourceLoader == applicationContext));
System.out.println("applicationEventPublisher == applicationContext :" + (applicationEventPublisher == applicationContext));
}
@PostConstruct
public void initByLookUp() {
getBean(BeanFactory.class);
getBean(ResourceLoader.class);
getBean(ApplicationEventPublisher.class);
getBean(ApplicationContext.class);
}
private <T> T getBean(Class<T> beanType) {
try {
return beanFactory.getBean(beanType);
} catch (NoSuchBeanDefinitionException e) {
System.err.println("当前类型:" + beanType.getName() + "无法在 BeanFactory 中查找!");
}
return null;
}
public static void main(String[] args) {
// 创建BeanFactory的容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册Configuration Class 配置类 -> Spring Bean
applicationContext.register(DependencySourceDemo.class);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找 DependencySourceDemo Bean
DependencySourceDemo demo = applicationContext.getBean(DependencySourceDemo.class);
// 显示的关闭spring应用上下文
applicationContext.close();
}
}
运行的结果如下:
这儿的对象我们称之为spring的非托管对象,那么是怎么注册的。具体的如下:
依赖对象
要素
要素
限制
要素
限制
具体的代码如下:
package org.learn.spring.dependency.source;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import javax.annotation.PostConstruct;
// ResolvableDependency 作为依赖来源
// 这儿的依赖的注入只能是类型的依赖的注入
public class ResolvableDependencySourceDemo {
@Autowired
private String value;
@PostConstruct
public void init(){
System.out.println(value);
}
public static void main(String[] args) {
// 创建BeanFactory的容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册Configuration Class 配置类 -> Spring Bean
applicationContext.register(ResolvableDependencySourceDemo.class);
applicationContext.addBeanFactoryPostProcessor(beanFactory -> {
// 注册 Resolvable Dependency
beanFactory.registerResolvableDependency(String.class, "Hello,World");
});
// 启动应用上下文
applicationContext.refresh();
// 显示的关闭spring应用上下文
applicationContext.close();
}
}
要素
限制
具体的代码如下
user.id=1
usr.name=甘雨
user.resource=classpath:/META-INF/default.properties
package org.learn.spring.dependency.source;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.Resource;
import javax.swing.text.StyleConstants;
// 外部化配置作为依赖的来源
@PropertySource(value = "classpath:/META-INF/default.properties",encoding = "UTF-8")
@Configuration
public class ExternalConfigurationDependencySourceDemo {
@Value("${user.id:-1}")
private Long id;
@Value("${usr.name:}")
private String name;
@Value("${user.resource:classpath:/META-INF/default.properties}")
private Resource resource;
public static void main(String[] args) {
// 创建BeanFactory的容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册Configuration Class 配置类 -> Spring Bean
applicationContext.register(ExternalConfigurationDependencySourceDemo.class);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找 ExternalConfigurationDependencySourceDemo Bean
ExternalConfigurationDependencySourceDemo demo = applicationContext.getBean(ExternalConfigurationDependencySourceDemo.class);
System.out.println("demo.id = " + demo.id);
System.out.println("demo.name = " + demo.name);
System.out.println("demo.resource = " + demo.resource);
// 显示的关闭spring应用上下文
applicationContext.close();
}
}
注册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的类型都是AbstractBeanDefinition AbstractBeanDefinition是所有的BeanDefinition的超类
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
// 这儿会校验BeanDefinition,这儿我不会做过多的赘述,后面有专门的博客来做介绍
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// 先查找对应的BeanDefinition是否存在
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
// 如果存在的话,看看这个BeanDefinition是否可以被覆盖,如果可以被覆盖,就重新存入Map中去,springFramework默认是true,是可以被覆盖,在springboot这个值被被改成了false,这儿就会抛出异常。
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 {
// 判断当前的BeanDefinition是否在创建中
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
// 将对应的key为BeanName value的值为BeanDefinition存放到beanDefinitionMap 中去
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
// 将对应的BeanName的Map进行更新
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
// 如果没有创建就将key为BeanName value的值为BeanDefinition存放到beanDefinitionMap 中去
this.beanDefinitionMap.put(beanName, beanDefinition);
// 将对应的BeanName存到beanDefinitionNames的List中去
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
从上面的的代码我们可以知道BeanDefinition
是存在beanDefinitionMap
的Map中去,key 是beanName
,value
是BeanDefinition
。同时将beanName
存到beanDefinitionNames
的List中去。
注册单例对象,具体的代码如下:
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
// 走来调用的是父类的方法
super.registerSingleton(beanName, singletonObject);
updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName));
clearByTypeCache();
}
可以看到我们走来调用的是父类的方法org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#registerSingleton
具体的代码如下:
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
Assert.notNull(beanName, "Bean name must not be null");
Assert.notNull(singletonObject, "Singleton object must not be null");
synchronized (this.singletonObjects) {
// 先获取对应的单例对象,如果存在直接抛出异常
Object oldObject = this.singletonObjects.get(beanName);
if (oldObject != null) {
throw new IllegalStateException("Could not register object [" + singletonObject +
"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
}
addSingleton(beanName, singletonObject);
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 将这个单例的对象存到对应Map中去,key为beanName value为singletonObject
this.singletonObjects.put(beanName, singletonObject);
// 从singletonFactories中移出beanName
this.singletonFactories.remove(beanName);
// 从earlySingletonObjects中移出beanName
this.earlySingletonObjects.remove(beanName);
// 从registeredSingletons中添加beanName
this.registeredSingletons.add(beanName);
}
}
从上面的代码我们可以知道单例的对象是添加singletonObjects
Map中key
为beanName
,value
是这个单例的对象。同时beanName
也会存到registeredSingletons
中去。
ResolvableDependency
最后是不受spring管理的对象,注册的过程如下:
@Override
public void registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue) {
Assert.notNull(dependencyType, "Dependency type must not be null");
if (autowiredValue != null) {
// 是ObjectFactory 直接抛出异常
if (!(autowiredValue instanceof ObjectFactory || dependencyType.isInstance(autowiredValue))) {
throw new IllegalArgumentException("Value [" + autowiredValue +
"] does not implement specified dependency type [" + dependencyType.getName() + "]");
}
// 将对应的对象存到resolvableDependencies Map中去 key为dependencyType value为autowiredValue
this.resolvableDependencies.put(dependencyType, autowiredValue);
}
}
上面的代码就是将这个对象存到resolvableDependencies
存到Map中去,key为dependencyType
value为autowiredValue
。上面的就是所有的依赖的注入的来源。而依赖的查找只会BeanDefinition的和singletonObjects这两个,这部分源码后面在介绍。
否, 依赖查找的来源仅限于 Spring BeanDefinition 以及单例对象, 而依赖注入的来源还包括 Resolvable Dependency 以及@Value 所标注的外部化配置
可以的, 单例对象的注册与 BeanDefinition
不同, BeanDefinition
会被 ConfigurableListableBeanFactory#freezeConfiguration()
方法影响, 从而冻结注册, 单例对象则没有这个限制。