继续上一节分析实例化所有非懒加载单例Bean流程,本节主要包含内容:
- DependsOn注解的源码分析
- 单例Bean、原型Bean、其他Scope Bean的源码分析
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {...}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//FactoryBean逻辑,上节讲过了
//这里会实例化FactoryBean本身,如果实现了SmartFactoryBean接口,并且isEagerInit=true
//也会立即初始化FactoryBean.getObject的对象
if (isFactoryBean(beanName)) {...}
else {
//这次走进getBean看下都干了啥
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {...}
}
本节主要讲getBean方法,getBean方法主要有三种用法,前两种之前都说过,再说一下第三种:
@Component
@Scope("prototype")
public class OrderService {
private User user;
//两个构造方法:
public OrderService() {
System.out.println(0);
}
public OrderService(User user) {
System.out.println(1);
this.user = user;
}
public void test() {
System.out.println("OrderService test");
}
}
OrderService有两个构造方法,而org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.String, java.lang.Object…)方法的作用就是,指定使用显式带参数的构造函数来创建Bean
入口getBean
回过来继续看源码:
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
//1.解析获取Bean的规范名称
// 传进来的name有多种情况:
// name可能是xxx或&xxx,如果name是&xxx,beanName就是xxx
// name也可能是别名,那么beanName就是id
String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
//2.单例池获取bean
// 提前检查单例池缓存,就算是原型bean,也会走一次,可能考虑到大多情况都是单例bean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {...}
//getObjectForBeanInstance上一节说过,专门为了特殊处理FactoryBean的情况
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//第一次getBean单例池里肯定没有,就会走创建逻辑
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {...}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
// 判断当前容器里是否有beanName对应的BeanDefinition
// 没有的话就从父工厂里获取、创建
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {...}
if (!typeCheckOnly) {...}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {...}
//获取合并之后的BeanDefinition
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//检查BeanDefinition是否是抽象的,抽象直接报错
checkMergedBeanDefinition(mbd, beanName, args);
//3.DependsOn依赖处理
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
//dependsOn表示当前beanName所依赖的
// 要求当前Bean创建之前dependsOn所依赖的Bean都必须创建好了
for (String dep : dependsOn) {
//beanName是不是被dep依赖了,如果是则出现了循环依赖
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//dep被beanName依赖了则存入dependentBeanMap中
//dep为key,beanName为value
registerDependentBean(dep, beanName);
try {
//创建所依赖的bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {...}
}
}
// Create bean instance.
// 4.创建Bean实例
// 4.1 单例bean处理
if (mbd.isSingleton()) {
//传入一个ObjectFactory工厂
sharedInstance = getSingleton(beanName, () -> {
try {
// 5.核心创建方法
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {...}
});
//无论单例、原型、其他Scope,创建的Bean都有可能是FactoryBean,所以专门处理一下,获取真正的Bean对象(上一节FactoryBean里讲过)
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//4.2 原型bean处理
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
//记录当前原型bean正在创建中
beforePrototypeCreation(beanName);
//创建原型bean,不用放到单例池
// 5.核心创建方法
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
//去除当前原型bean正在创建中的标记
afterPrototypeCreation(beanName);
}
//无论单例、原型、其他Scope,创建的Bean都有可能是FactoryBean,所以专门处理一下,获取真正的Bean对象(上一节FactoryBean里讲过)
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
//4.3 其他scope情况处理
else {
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 {
//和单例Bean的代码风格很像,也是传入一个ObjectFactory
//先判断当前作用域中是否有这个对象,有直接返回
//没有,则利用ObjectFactory创建对象,再放入作用域中保存
Object scopedInstance = scope.get(beanName, () -> {
//标记正在创建中
beforePrototypeCreation(beanName);
try {
// 5.核心创建方法
return createBean(beanName, mbd, args);
}
finally {
//去除创建中标记
afterPrototypeCreation(beanName);
}
});
//无论单例、原型、其他Scope,创建的Bean都有可能是FactoryBean,所以专门处理一下,获取真正的Bean对象(上一节FactoryBean里讲过)
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {...}
}
}
catch (BeansException ex) {...}
finally {...}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
1. 解析获取Bean的规范名称
应用场景
@Bean设置别名:
@ComponentScan("com.yth")
public class AppConfig {
@Bean({"user1", "user2", "user3"})
public User user() {
return new User();
}
}
xml方式设置别名:
//多个别名之间,可用空格、逗号、分号,或者三者混合
<bean id="user" name="user1 user2 user3" class="com.yth.service.User"/>
Spring底层针对别名,存了一个aliasMap:key是别名,value是beanName
源码分析
org.springframework.beans.factory.support.AbstractBeanFactory#transformedBeanName
getBean传进来的name可能有多种情况(别名、&xxx、beanName),不管什么情况,通过该方法都会找到对应Bean的规范名称
protected String transformedBeanName(String name) {
//BeanFactoryUtils.transformedBeanName处理&xxxx这种想要获取BeanFactory本身的情况
//canonicalName处理别名的情况
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
org.springframework.beans.factory.BeanFactoryUtils#transformedBeanName
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
//FACTORY_BEAN_PREFIX = "&";
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
//由此可见&&&&&&&&这个也行
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
org.springframework.core.SimpleAliasRegistry#canonicalName
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
//aliasMap,key是别名,value是beanName
//这里做了do while,考虑到一种复杂情况,给别名起别名...
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
2. 单例池获取bean
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
// singletonObjects就是单例池,
Object singletonObject = this.singletonObjects.get(beanName);
// 后面逻辑暂时不用关注,以后讲循环依赖会说
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {...}
return singletonObject;
}
singletonObjects就是单例池
3. DependsOn依赖处理
应用场景
@Component
//告诉Spring,如果想要创建OrderService对象,则需要先把beanName为user的对象创建出来
@DependsOn("user")
public class OrderService {
public void test() {
System.out.println("OrderService test");
}
}
@Component
public class User {
public User() {
System.out.println(1);
}
}
@Autowired也表示一种依赖关系
源码分析
if (dependsOn != null) {
//dependsOn表示当前beanName所依赖的
// 要求当前Bean创建之前dependsOn所依赖的Bean都必须创建好了
for (String dep : dependsOn) {
//3.1 beanName是不是被dep依赖了,如果是则出现了循环依赖
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//3.2 存储依赖关系
//dep被beanName依赖了则存入dependentBeanMap中
//dep为key,beanName为value
registerDependentBean(dep, beanName);
try {
//创建所依赖的bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {...}
}
}
3.1 判断DependsOn是否出现循环依赖
DependsOn注解引发的循环依赖是没法解决的,直接抛异常。
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#isDependent(java.lang.String, java.lang.String)
//判断dependentBeanName是不是依赖了beanName,true:是
protected boolean isDependent(String beanName, String dependentBeanName) {
synchronized (this.dependentBeanMap) {
return isDependent(beanName, dependentBeanName, null);
}
}
private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
if (alreadySeen != null && alreadySeen.contains(beanName)) {
//依赖关系形成的链条又走到了"自己",说明之前已经处理过了,不依赖,直接结束。
return false;
}
//获取当前beanName的规范beanName
String canonicalName = canonicalName(beanName);
//获取当前beanName被哪些Bean依赖了
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
return false;
}
if (dependentBeans.contains(dependentBeanName)) {
//dependentBeanName是被当前beanName依赖的Bean
//dependentBeans是依赖当前beanName的Bean
//包含说明出现循环依赖
return true;
}
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
alreadySeen.add(beanName);
//递归处理,判断依赖当前beanName的bean会不会依赖dependentBeanName
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}
有点绕,看个图:
3.2 存储@DependsOn依赖关系
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#registerDependentBean
注意传进来的入参,beanName是依赖dep的
public void registerDependentBean(String beanName, String dependentBeanName) {
//此时beanName其实是dep,dependentBeanName为beanName
//dependentBeanName依赖beanName
String canonicalName = canonicalName(beanName);
synchronized (this.dependentBeanMap) {
//dependentBeanMap,表示某个Bean被哪些Bean依赖了
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
//添加失败,则说明dependentBeans已经存在了,之前处理过了
return;
}
}
synchronized (this.dependenciesForBeanMap) {
//dependenciesForBean,表示某个Bean依赖了哪些Bean
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
两个map,双向存储:
- dependentBeanMap,表示某个Bean被哪些Bean依赖了
- dependenciesForBean,表示某个Bean依赖了哪些Bean
4. 创建Bean实例
4.1 单例Bean处理
// Create bean instance.
// 4.创建Bean
// 4.1 单例bean处理
if (mbd.isSingleton()) {
//lambda表达式,传入一个ObjectFactory工厂
//getSingleton:先从单例池获取Bean,获取不到则利用ObjectFactory工厂创建Bean,再放到单例池
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {...}
});
//无论单例、原型、其他Scope,创建的Bean都有可能是FactoryBean,所以专门处理一下,获取真正的Bean对象
//上一节FactoryBean里讲过
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
//先从单例池获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {...}
if (logger.isDebugEnabled()) {...}
//记录当前单例Bean正在创建中(和循环依赖有关,以后讲。)
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {...}
try {
//核心在这,工厂创建单例bean
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {...}
catch (BeanCreationException ex) {...}
finally {
if (recordSuppressedExceptions) {...}
//去除创建中标记
afterSingletonCreation(beanName);
}
// 添加到单例池
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//添加到单例池
this.singletonObjects.put(beanName, singletonObject);
//下面这些和循环依赖有关,以后讲
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
4.2 原型Bean处理
//4.2 原型bean处理
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
//记录(标记)当前原型bean正在创建中
beforePrototypeCreation(beanName);
//创建原型bean,仅仅创建,也没存储到任何地方
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
//去除当前原型bean正在创建中的标记
afterPrototypeCreation(beanName);
}
//无论单例、原型、其他Scope,创建的Bean都有可能是FactoryBean,所以专门处理一下,获取真正的Bean对象
//上一节FactoryBean里讲过
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
beforePrototypeCreation/afterPrototypeCreation利用ThreadLocal做了一个记录标记正在创建中:
protected void beforePrototypeCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
if (curVal == null) {
this.prototypesCurrentlyInCreation.set(beanName);
}
else if (curVal instanceof String) {
Set<String> beanNameSet = new HashSet<>(2);
beanNameSet.add((String) curVal);
beanNameSet.add(beanName);
this.prototypesCurrentlyInCreation.set(beanNameSet);
}
else {
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.add(beanName);
}
}
protected void beforePrototypeCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
if (curVal == null) {
this.prototypesCurrentlyInCreation.set(beanName);
}
else if (curVal instanceof String) {
Set<String> beanNameSet = new HashSet<>(2);
beanNameSet.add((String) curVal);
beanNameSet.add(beanName);
this.prototypesCurrentlyInCreation.set(beanNameSet);
}
else {
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.add(beanName);
}
}
4.3 其他Scope Bean处理
使用场景
可以利用@Scope注解可设置Bean的作用域, SpringWeb封装了一下:@RequestScope、@SessionScope、@ApplicationScope…
源码分析
//4.3 其他scope情况处理
else {
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 {
//和单例Bean的代码风格很像,也是传入一个ObjectFactory
//先判断当前作用域中是否有这个对象,有直接返回
//没有,则利用ObjectFactory创建对象,再放入作用域中保存
Object scopedInstance = scope.get(beanName, () -> {
//标记正在创建中
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
//去除创建中标记
afterPrototypeCreation(beanName);
}
});
//无论单例、原型、其他Scope,创建的Bean都有可能是FactoryBean,所以专门处理一下,获取真正的Bean对象
//上一节FactoryBean里讲过
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
比如request域,底层就是利用request.getAttribute(“beanName”)先判断有没有对象,没有再调用ObjectFactory.getObject创建,然后再request.setAttribute保存:
get方法在父抽象类中:
public abstract class AbstractRequestAttributesScope implements Scope {
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
//name就是Bean的名字
Object scopedObject = attributes.getAttribute(name, getScope());
if (scopedObject == null) {
//不存在则利用objectFactory创建,然后在放到作用域中
scopedObject = objectFactory.getObject();
attributes.setAttribute(name, scopedObject, getScope());
// Retrieve object again, registering it for implicit session attribute updates.
// As a bonus, we also allow for potential decoration at the getAttribute level.
Object retrievedObject = attributes.getAttribute(name, getScope());
if (retrievedObject != null) {...}
}
return scopedObject;
}
...
}
看下attributes.getAttribute实现,我们只关注Servlet的实现
org.springframework.web.context.request.ServletRequestAttributes#getAttribute
public Object getAttribute(String name, int scope) {
if (scope == SCOPE_REQUEST) {
if (!isRequestActive()) {...}
//request,这
return this.request.getAttribute(name);
}
else {
HttpSession session = getSession(false);
if (session != null) {
try {
//session,这
Object value = session.getAttribute(name);
if (value != null) {
this.sessionAttributesToUpdate.put(name, value);
}
return value;
}
catch (IllegalStateException ex) {...}
}
return null;
}
}
set同理:org.springframework.web.context.request.ServletRequestAttributes#setAttribute
public void setAttribute(String name, Object value, int scope) {
if (scope == SCOPE_REQUEST) {
if (!isRequestActive()) {
throw new IllegalStateException(
"Cannot set request attribute - request is not active anymore!");
}
this.request.setAttribute(name, value);
}
else {
HttpSession session = obtainSession();
this.sessionAttributesToUpdate.remove(name);
session.setAttribute(name, value);
}
}
另外Scope是什么时候注册的?如果引入了Spring-web的包:
org.springframework.web.context.support.WebApplicationContextUtils#registerWebApplicationScopes(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, javax.servlet.ServletContext)
5. 创建Bean对象
核心方法
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
下节讲。