Spring创建Bean实例分析
文章主要讲解Spring的createBean方法,createBean之前一些操作就不介绍了。抛开Spring来说Java里面创建一个对象分成以下两个步骤:
- Object object = new Object(); 创建一个对象(这时候object对象在Java堆中是已经分配了内存空间)
- 对这个对象进行属性赋值
带着这个思路我们去看下Spring是如何去创建Bean实例的,阅读的代码入口如下:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 我们从这里开始看了
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
/****************省略 ****************/
/****************省略 ****************/
/****************省略 ****************/
}
1、Spring createBeanInstance
createBeanInstance看英文名大概知道是什么意思。这个方法主要功能是根据BeanDefinion对象去创建一个Bean(换句话说就是根据BeanDefinion反射去创建一个对象)
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 我们从这里开始看起,转到代码定义
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
1、判断BeanDefinion对象是否有FactoryMethodName属性,然后根据FactoryMethod来创建实例,创建好直接返回实列(这个时候在JVM堆中已经存在对象了),代码如下:
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
2、如果BeanDefinion没有FactoryMethodName属性,就会调用determineConstructorsFromBeanPostProcessors 方法收集有@Autowried注解的构造方法,如果存在此类的构造方法反射来创建一个bean实例
// 这个方法主要是收集存在@Autowried注解的构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 然后把构造方法里面的引用参数类型进行注入,那下面的案例来说,这行代码最终会通过beanFactory.getBean(beanName) 得到一个bean注入到这个构造方法里面去
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
3、@Autowried构造方法里面的参数是调用 autowireConstructor()方法注入进入的(它的后面还是调用了**beanFactory.getBean(beanName)**操作,代码太深了我贴一些关键步骤的代码 。有兴趣的可以按照以下的代码跟进去看看 )
// 1、ctors 参数注入
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
// 2、构造ctors构造方法参数, 我们主要看 **createArgumentArray**
ArgumentsHolder argsHolder;
if (resolvedValues != null) {
try {
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
// 获取注入的参数,我们主要看这个方法
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
}
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next constructor.
if (causes == null) {
causes = new LinkedList<>();
}
causes.add(ex);
continue;
}
}
else {
// Explicit arguments given -> arguments length must match exactly.
if (paramTypes.length != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
// 3、这个方法太深了,直截取关键部分代码出来
try {
// 主要看resolveAutowiredArgument方法
Object autowiredArgument = resolveAutowiredArgument(
methodParam, beanName, autowiredBeanNames, converter, fallback);
args.rawArguments[paramIndex] = autowiredArgument;
args.arguments[paramIndex] = autowiredArgument;
args.preparedArguments[paramIndex] = new AutowiredArgumentMarker();
args.resolveNecessary = true;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
}
// 4、转到resolveAutowriedArgument这个方法 ,看主要的代码
try {
return this.beanFactory.resolveDependency(
new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
}
catch (NoUniqueBeanDefinitionException ex) {
throw ex;
}
// 5、这个方法看 **doResolveDependency** ,这个方法站到定义
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
// 6、 **descriptor.resolveCandidate** 这个方法转到定义
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
// 如果这个参数是一个class 引用类型参数,就会执行这段代码的
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
// 7、继续跟进去你就会发现最终调用的是beanFactory.getBean(beanName) 操作
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
// 最后还是会调用getBean获取实例
return beanFactory.getBean(beanName);
}
4、绝大部分操作都会采用无参函数的实例化的,无参构造代码就比较好理解,代码如下:
// 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);
小结:这个时候一个对象已经创建好了,在JVM堆中已经存在了,但是这个bean是一个半成品 。因为这个bean里面的很多属性没有做依赖注入。我们要对一个bean做依赖注入,首先我们通过反射来获取有 @Autowried、@Resource、@PostConstructor、@PreDestory 注解的方法 和 属性信息
2、Spring 收集Metadata
上面我们介绍了 spring创建bean,但是这个bean是一个半成品,因为这个bean还没有做依赖注入。要做依赖注入之前我们是不是先要把需要注入的信息收集起来 ,接下来我们介绍 applyMergedBeanDefinitionPostProcessors这个方法
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
这个MergedBeanDefinitionPostProcessor是一个接口,我们看下相关的实现类
CommonAnnotationBeanPostProcessor
1、我们先来看下CommonAnnotationBeanPostProcessor这个实现类 ,看这个实现类之前我先把这个类的无参构造方法
// 我插累,这里面有PostConstruct 和 PreDestroy ,转到定义两个注解
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
}
// 这个方法就是通过反射收集 @PostConstruct 、@PreDestroy 、@Resource 注解的信息
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 这个方法就是通过反射收集 @PostConstruct 、@PreDestroy 注解 方法信息
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
// 这个方法也是通过放射收集 @Resource 注解的 字段信息、方法信息
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
2、CommonAnnotationBeanPostProcessor -> postProcessMergedBeanDefinition 主要以下几件事
- 收集了有@PostConstruct 、@PreDestroy 注解的方法信息 ,并把它包装成 LifecycleMetadata 对象存入到lifecycleMetadataCache 这个Map里面
- 收集了有@Resource 注解的方法、字段信息,并把它包装成InjectionMetadata对象存入到 injectionMetadataCache 这个Map里面
- 这个收集代码就不贴出来了,本人是一个小白都能看得懂,挺简单的
AutowiredAnnotationBeanPostProcessor
1、接下来我们来看下AutowiredAnnotationBeanPostProcessor实现类,我们同样来看下无参构造方法。
// 出现了 Autowired 注解 和 Value 注解 ,把它存入到 autowiredAnnotationTypes里面去了,这个记住以下,后面收集的时候需要用的到这个变量
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
// 这个方法来收集有@Autowired 方法和字段信息
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 这个方法也是通过放射收集 @Autowired 注解的 字段信息、方法信息
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
总结: 收集了有 @Autowired 注解的方法、字段信息,并把它包装成InjectionMetadata对象存入到 injectionMetadataCache 这个Map里面( 这些代码容易理解,没啥逻辑的所以不贴出来了 )
3、Spring populateBean 依赖注入
// 这个方法先不去了解
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
循环依赖注入这里不讲解了,所以这个方法先不看了,我们直接看 populateBean 方法 ,这个方法就是DI 核心注入方法
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 这个方法就是DI 核心注入方法
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
1、转到populateBean方法,我们先来阅读一段很有意思的代码
// 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.
boolean continueWithPropertyPopulation = true;
// 这段代码很有意思,写一个InstantiationAwareBeanPostProcessor接口实现类,可以让所有的bean不能依赖注入
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
// 是否需要依赖注入
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 如果不需要直接return了
if (!continueWithPropertyPopulation) {
return;
}
// 这里我不多说了,那些想搞破坏的同志们.......
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 依赖注入过程, @Autowired的支持
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 老版本spring用这个方法完成依赖注入, @Autowired的支持
pvsToUse = ibp.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);
}
// 老版本用 <property name="username" value="Jack" />
// 标签做依赖注入,复杂且无用
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
2、我们直接看这段代码 postProcessProperties 这个方法 ,InstantiationAwareBeanPostProcessor 是一个接口,我们来看下接口实现类
3、我们先来看AutowiredAnnotationBeanPostProcessor 这个类的 postProcessProperties 方法
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 看到这个对象是不是很熟悉,上面刚介绍过的,调用postProcessMergedBeanDefinition收集需要注入的信息
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//这一段转到定义,你就会发现他是一个一个循环,然后反射赋值
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
// 循环注入
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
// 循环injectElements
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
// 我们在转到定义去看看这个
element.inject(target, beanName, pvs);
}
}
}
// 用过反射的就看的出来,这里面反射赋值
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
// 这个需要注入的bean 最终还是通过beanFactory.getBean() 去获取的
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
//如果value有值,就反射field.set赋值
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
4、上面inject 方法如果简单的说只做了两件事 :
- 通过beanFactory.getBean(beanName) 获取需要注入的bean对象
- 得到注入的bean对象后,通过反射赋值
- 其它的就不一一列举了,流程度差不多
4、Spring initializeBean后置操作
当一个bean在spring容器中完成了创建和依赖注入,这个bean就标识可以使用了。但是spring还定义了一些接口比如:BeanFactoryAware、InitializingBean 接口及@PostConstruct注解的方法
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//1 、调用 Aware方法
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 2、对bean中的特殊方法的调用,比如@PostConstruct、Aware接口的方法调用
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 2、InitializingBean 接口, afterPropertiesSet ,init-method属性调用
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 3、这个是AOP的切入点,这里不详细介绍 。。。。。
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
总结
Spring 的doCreateBean 操作流程如下:
- 通过 createBeanInstance 创建bean 实例(这个bean对象还是一个半成品,需要做依赖注入的属性都还没有注入)
- 通过 MergedBeanDefinitionPostProcessor -> postProcessMergedBeanDefinition 来收集bean需要注入的(方法、属性)并且封装成Metadata对象存入缓存中
- 通过 InstantiationAwareBeanPostProcessor -> postProcessProperties 方法来循环注入相应的bean实例(这里需要补充一句,需要注入的对象也是通过beanFactory.getBean(beanName)去获取的,得到bean实例后,在通过反射方式赋值给目标对象)
- 最后还是要说一句,本人也是小白。博客上很多关于spring的优秀文章,本人就是为了加深理解,就在这里抛砖引玉。