/**
* 一个单例bean的依赖注入和查找
*/
public class SingletonBeanInjectLock {
public static void main(String[] args) {
// 创建Ioc容器
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
// 定义初始化类
beanDefinition.setBeanClass(Person.class);
// 用构造函数的方式初始化类
ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
constructorArgumentValues.addGenericArgumentValue("张三");
constructorArgumentValues.addGenericArgumentValue("北京");
constructorArgumentValues.addGenericArgumentValue(14212123);
beanDefinition.setConstructorArgumentValues(constructorArgumentValues);
//将beanDefinition注册到容器中
beanFactory.registerBeanDefinition("person",beanDefinition);
System.out.println(beanFactory.getBean("person"));
}
}
这里我们直接定义了一个实例,采用手动注册的方式将bean对象注入到ioc容器中。我们来看这段代码在源码中具体做了哪些事情。
第一步创建DefaultListableBeanFactory对象这个就不用说了,看下面的GenericBeanDefinition。之前我们说过beanDefinition是spring中bean对象的描述类,包含一些bean对象的配置信息。比如像作用域啊,bean对象的类、构造函数、init-method、工厂类之类的。
这里我们创建了一个GenericBeanDefinition,并且将他的类设置为Person,并且设置了它的构造函数的参数,用构造函数初始化Bean对象。然后通过registerBeanDefinition注册到容器中。
这里的注入具体干了什么事情呢?
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
// 根据beanName查看是否已经有该bean对象存在
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
// 将之前的beanDefinition覆盖掉
// (这里删除了部分代码,实际上容器有个allowBeanDefinitionOverriding信息
// 默认为true,如果不为true不会进行覆盖操作)
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// 这里是判断当前是否已经有bean被创建了,如果有的话,需要加锁来保障线程安全
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
// 保存该beanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
// 从手动注册的bean类表中删除
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
// 如果当前已经有缓存的beanDefinition,则重置beanDefinition
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
// 清空allBeanNamesByType、singletonBeanNamesByType缓存信息
clearByTypeCache();
}
}
这样就把bean对象存到了Ioc容器中。那么当我们调用getBean时做了什么呢?
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object bean;
// 查看当前是否是单例Bean对象
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// 从缓存中获取单例Bean对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 找到对应的BeanDefinition对象
BeanFactory parentBeanFactory = getParentBeanFactory();
// 类似双亲委派机制,先找父容器中是否有,优先从父容器中获取bean信息
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 这里可以有些疑问,什么是MergedBeanDefinition?
// 实际上之前我们在DefaultListableBeanFactory注册成功之后,
// 把对应的beanDefinition存到beanDefinitionMap中了。
// 但是在AbstractBeanFactory中有个mergedBeanDefinitions,
// 我们最终取的BeanDefinition也是从mergedBeanDefinitions中取的,
// 所以我们需要合并到mergedBeanDefinitions中。
// 这个地方做的事情就是如果当前这个BeanDefinition需要合并,就放到
// mergedBeanDefinitions中,再返回该对象。
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 查找依赖,并将依赖实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
// 创建bean实例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 这个方法实际上是写在AbstractAutowireCapableBeanFactory类中的
// 待会再看
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
// 跟上面的isPrototypeCurrentlyInCreation对应
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
// 这个地方是给其他作用域用的 比如RequestScope、SessionScope
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
// 跟上面的isPrototypeCurrentlyInCreation对应
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
return (T) bean;
}
spring创建对象的类:
实际上最后是InstantiationStrategy决定用哪种策略去创建初始化bean对象。
一共是两种,上面的SimpleInstantiationStrategy直接就用的Java反射。CglibSubclassingInstantiationStrategy采用cglib生成类方式,实例化对象。