Spring Boot bean解析
Bean配置
配置bean可以通过Xml和注解进行配置,在本文暂不介绍Xml方式,只介绍注解方式,注解有以下几种方式配置Bean。
@Component
声明,其他还有@Service 、@Repository
等@Component public class Teacher extends Person { @Override public String getProfessional() { return "teacher"; } }
配置类中使用
@Bean
@Configuration public class StudentConfig { @Bean public Person student() { return new Student(); } }
实现
FactoryBean
@Component public class MyWorker implements FactoryBean<Person> { @Override public Person getObject() throws Exception { return new Worker("worker"); } @Override public Class<?> getObjectType() { return Person.class; } }
实现
BeanDefinitionRegistryPostProcessor
@Component public class BeanRegister implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(); rootBeanDefinition.setBeanClass(Salesman.class); beanDefinitionRegistry.registerBeanDefinition("salesMan", rootBeanDefinition); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { } }
实现
ImpoprtBeanDefinitionRegister
public class BeanImport implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(); rootBeanDefinition.setBeanClass(Coder.class); registry.registerBeanDefinition("coder", rootBeanDefinition); } }
在启动类加上:
@Import(BeanImport.class)
Bean解析
Bean解析核心逻辑在org.springframework.context.support.AbstractApplicationContext#refresh
方法中,该方法的核心流程如下图所示:
prepareRefresh方法
prepareRefresh主要做了以下几个事情:
- 容器状态设置,表明容器为active状态
- 初始化属性设置
- 检查必备属性是否存在
属性检查支持自定义,示例如下:
public class FirstInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
environment.setRequiredProperties("xw.age");
}
}
在初始化器中添加属性检查的逻辑,上述示例将在启动时检查xw.age
属性是否存在,如果不存在,将抛出如下异常:
prepareBeanFactory
prepareBeanFactory方法主要做了以下几个事情:
- 设置beanFactory的一些属性
- 添加后置处理器
- 设置忽略的自动装配接口
- 注册一些组件
postProcessBeanFactory
postProcessBeanFactory中主要用于子类重写在BeanFactory完成创建后做进一步设置l
invokeBeanFactoryPostProcessors
invokeBeanFactoryPostProcessors方法主要逻辑:
调用BeanDefinitionRegistryPostProcessor实现向容器中添加Bean的定义,具体实现请参考上面
调用BeanFactoryPostProcessor实现向容器内bean的定义添加属性,实现如下所示:
@Component public class FirstBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { Salesman salesman = configurableListableBeanFactory.getBean(Salesman.class); salesman.setAge(100); } }
上述代码向salesman bean中设置了age属性,赋值为100。
initMessageSource
该方法主要逻辑是初始化国际化相关属性。
initApplicationEventMulticaster
改方法主要逻辑是初始事件广播器。
onRefresh
创建web容器。
registerListeners
将监听器事件监听器添加到广播器中。
finishBeanFactoryInitialization
初始化未初始化的单例bean实例,实例化的流程如下:
doGetBean方法如下:
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 获取bean名称,如果是beanFactory对象在前面加上&标记
String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
// 从缓存获取单例bean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
//判断bean对象标记是否正在创建中,如果正在创建中则不应该继续下去,出现依赖循环就会出现这个错误
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
// 检查父容器是否存在,尝试从父容器中获取
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);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
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) {
//bean 中@DependsOn信息,用于标记bean之间初始化顺序,优先创建@DependsOn中的bean
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.
// 创建单例对象,并加入一级缓存
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
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 是FactoryBean ,再获取真正的对象
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//作用域 = prototype,因为不会放入缓存中,每次获取都要重新创建
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// session request 这些作用域,由作用域容器去管理这些对象
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 {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
// 返回初始化成功的对象
return adaptBeanInstance(name, beanInstance, requiredType);
}
上述方法整体流程如下:
- 从三级缓存获取bean实例
- 如果缓存中不存在,尝试从父容器中获取
- 如果父容器中不存在,开始进入实例化阶段,获取RootBeanDefinition,优先加载@DependsOn上的bean
- 调用
AbstractBeanFactory#createBean
进行实例化,完成后加入一级缓存,并从二级缓存和三级缓存移除。
查看createBean方法:
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//通过BeanPostProcessors 增强返回一个代理对象,这个生成AOP的代理对象,使用多个BeanPostProcessors来处理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 对象实例化
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
进一步查看doCreateBean
方法,主要流程为:
- 初始化实例,创建对象完成,并且添加到3级缓存。第3级缓存常常用于存储代理对象,因为有些类需要动态代理方法,需要生成代理对象,会委派给第三级缓存方法ObjectFactroy去实现的,普通对象如果不需要会直接返回。
- 对实例化bean进行属性注入
- 执行初始化方法,DisposableBean接口加入到disposableBeans容器中
查看属性注入方法逻辑:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
// 判断是否支持注入
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//获取注入方式 根据名称注入、根据类型注入、构造器注入
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 设置属性
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
bean的注入都是InstantiationAwareBeanPostProcessor
类进行处理的,该是BeanPostProcessor
的子接口,该接口添加了实例化前回调,以及实例化后设置显式属性或自动装配之前的回调。方法如下:
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
//在目标bean初始化前被调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,
//所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,
//后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
// 在bean实例化之后(通过构造函数或工厂方法),但在Spring属性填充(从显式属性或自动装配)发生之前执行操作。
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
//对属性进行赋值
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
//对bean属性值赋值后调用,对属性值的修改。如果postProcessAfterInstantiation方法返回false,
//该方法可能不会被调用。可以在该方法内对属性值进行修改
@Deprecated
@Nullable
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
}
InstantiationAwareBeanPostProcessor 接口实现类主要分3个
ConfigurationClassPostProcessor
:看类名就知道处理@Configuration实例化。CommonAnnotationBeanPostProcessor
:实现JSR-250 注解、@Resource,@EJB、@WebServiceRef,@WebServiceContext,@PostConstrusct、@PreDestory这些注解实现。AutowiredAnnotationBeanPostProcessor
:实现 @Autowired、@Value注入,并且支持JSR-330's @Inject注解注入的。
@Autowired和@Resource注解使用
bean的注入常用的有@Autowired注解和@Resource注解,区别如下:
@Autowired是根据类型进行注入,当有多个一样的类型时,可通过使用名称装配结合@Qualifier注解进行使用
@Resource有name和type两个属性,如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常,如果指定了name,则从上下文中查找名称匹配的bean进行装配,找不到则抛出异常,如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常。
finishRefresh
核心逻辑:
- 初始化生命周期处理器
- 调用生命周期处理器的onRfresh方法
- 发布ContextRefreshedEvent事件
- JMX相关处理
三级缓存
/** Cache of singleton objects: bean name to bean instance. */
// 一级缓存 用于存放完全可以使用单例bean,也就是初始化完成并且注入所有依赖
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
//二级缓存 过早暴露单例对象,此时bean刚刚完成初始化,未完成属性注入和执行 init 方法
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
// 三级缓存 装载创建bean的工厂对象
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
三级缓存主要作用: 创建对象ObjectFactory首先放入三级换缓存中,当调用getObject 创建实例时,会将创建好对象加入二级缓存中,并且删除三级中缓存,当对象已经完成初始化方法和属性注入,再将缓存添加到一级缓存中,并且删除二级缓存。主要用来解决单例bean的循环依赖问题。