实例化阶段
类加载(Bean的ClassLoading):BeanDefinition中的Class信息从过去的一个文本信息变成一个实在的CLass对象,这个过程称为Bean的class Loading,接下来我们继续讨论这个类信息如何变为我们的一个Bean的实例,也就是我们通常讲的Bean的实例化阶段。实例化阶段分为3个阶段,实例化前阶段,实例化中阶段,实例化后阶段。
Spring Bean实例化前阶段
- instantiationAwareBeanPostProcessor#postProcessorBeforeInstantiation
Bean实例化前阶段,在实例化之前的操作,这个操作会打破Bean的注册。能够帮助我们提前去生成一些类似与代理对象的东西,来替换掉默认的Spring IOC里面的实现内容。(非主流生命周期,很少有人射猎):
class MyInstantiationAwareBeanPostProocessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throwos BeansException {
if(ObjectUtils.nullSafeEquals("superUser", beanName) && SuperUser.class.equals(beanClass)) {
// 覆盖superUser bean的配置
return new User();
}
// 保持 Spring IoC 容器的其他实例化操作
return null;
}
}
Spring Bean实例化阶段
实例化方法:
- 1.传统实例化方式-实例化策略-InstantiationStrategy
- 2.构造器依赖注入(按照类型的方式注入)
/**
* Create a new instance for the specified bean, using an appropriate instantiation strategy:
* factory method, constructor autowiring, or simple instantiation.
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
// 构造器注入
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
// 传统实例化方法
return instantiateBean(beanName, mbd);
}
传统实例化方法
// Strategy for creating bean instances.
// 用cglib产生一个动态的子类(字节码自动生成子类)
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
// Instantiate the given bean using its default constructor.
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
Object beanInstance;
final BeanFactory parent = this;
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
Spring Bean实例化后阶段
- Bean属性赋值(Populate)判断:
- InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
赋值的前置操作阶段。可以跳过原有bean属性植入,手动的去植入,类似于一种拦截机制。此时Bean的实例化完成了,但是属性的赋值并没有完成。
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
// 此时Bean的实例化已经完成了,但是属性的赋值并没有完成
if(ObjectUtils.nullSafeEquals("user", beanName) && User.class.equals(bean.getClass))) {
User user = (User) bean;
user.setId(2L);
user.setName("mercyblitz");
// "user"对象不允许属性赋值(配置元信息 -> 属性值)
return false; // 跳过原有bean属性植入,手动的去植入,类似于一种拦截机制。此时Bean的实例化完成了,但是属性的赋值并没有完成。
}
return true; // 按原有逻辑
}
Spring bean属性赋值前阶段
** 赋值前阶段-- 赋值阶段 – invokeAwareMethods – postProcessBeforeInitialization(invokeInitMethods(postConsturct)) – invokeInitMethods(afterPropertiesSet -> invokeCustomInitMethod) **
- Bean属性值元信息 - PropertyValues
- Bean属性赋值前回调
- Spring 1.2-5.0:InstantiationAwareBeanPostProcessor#postProcessPropertyValues
- Spring 5.1:InstantiationAwareBeanPostProcessor#postProcessProperties
Bean的属性赋值前的一个回调,可以动态调整原来的PropertyValues。
// 可以去拦截,可以把配置里面的值进行修改
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
return null; // 默认不做任何修改
}
static class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
// Returnng false will also prevent any subsequent InstantiationAwareBeanpostProcessor instances being invoked on this bean instance.
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if(ObjectUtils.nullSafeEquals("user", beanName) {
return false;
}
return true;
}
// postProcessAfterInstantiation返回了false的时候,postProcessProperties不会被调用
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Objecjt bean, String beanName) throws BeansException {
if(ObjectUtils.nullSafeEquals("userHolder", beanName)) {
final MutablepropertyValues propertyValues = new MutablePropetyValues();
propertyValues.addPropertyValue("number", "1");
return propertyValues;
}
return null;
}
}
Spring Bean Aware接口回调阶段
回调,在bean的initializing阶段
Spring Aware接口:
- BeanNameAware
- BeanClassLoaderAware
- BeanFactoryAware
普通的BeanFactory只会有这三种回调
ApplicationContext回调方式多一些,有下面这几种
- EnvironmentAware
- EmbeddedValueResolverAware
- ResourceLoaderAware
- ApplicationEventPublisherAware
- MessageSourceAware
- ApplicationContextAware
public Class AbstractApplicationContext {
...
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//config the bean factory with context callbacks
// 通过添加beanPostProcessor来完成Aware的 回调,是第一位的beanPostProcessor
// 在BeforeInitialization之前,就会把响应的Aware进行回调操作
// 只能在 ApplicationContext进行回调
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
}
}