为了搞明白自动装配原理,需要知道spring容器管理bean的生命周期
Spring Bean 生命周期流程图
bean自身方法的生命周期
分为四步:
//执行此段代码,spring容器的bean执行实例化、属性赋值、初始化
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//关闭容器,执行销毁
classPathXmlApplicationContext.close();
1、实例化
- 读取spring配置文件
- 通过反射进行bean的实例化(eg:通过BeanFactory实例化)
2、属性赋值
- 解析自动装配(byName、byType、constractor、default)DI的体现
- 循环依赖
3、初始化
- 调用XXXAware回调方法
- 调用初始化生命周期回调(三种)
- 如果bean实现aop创建动态代理
4、销毁
- 在spring容器关闭的时候进行调用
- 调用初始化生命周期回调
对应上述文字,下图展示了bean装载到spring应用上下文种的一个典型的生命周期过程
@Autowired注解的自动装配过程
先说结论:
@Autowired是在Bean属性赋值阶段进行装配,通过Bean的后置处理器进行解析
1、在创建一个spring上下文的时候在构造函数中注册AutowiredAnnotationBeanPostProcessor
2、在Bean的创建过程中进行解析
1、在实例化后预解析(解析@Autowired标注的属性、方法,比如:把属性的类型、名称、属性所在的类...元数据缓存)
2、在属性赋值阶段真正的注入(拿到上一步缓存的元数据去ioc容器进行查找,并且返回注入)
a.首先根据解析的元数据拿到类型去容器种查找
*如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;
*如果查询的结果不止一个,那么@Autowired会根据名称来查找
*如果上述查找结果为空,那么就会抛出异常。
大致流程图如下:
@Autowired字段注入源码分析
/* ......源码注解过多,只贴一部分有用的
* <h3>Not supported in {@code BeanPostProcessor} or {@code BeanFactoryPostProcessor}</h3>
* <p>Note that actual injection is performed through a
* {@link org.springframework.beans.factory.config.BeanPostProcessor
* BeanPostProcessor} which in turn means that you <em>cannot</em>
* use {@code @Autowired} to inject references into
* {@link org.springframework.beans.factory.config.BeanPostProcessor
* BeanPostProcessor} or
* {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessor}
* types. Please consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}
* class (which, by default, checks for the presence of this annotation).
*
* @author Juergen Hoeller
* @author Mark Fisher
* @author Sam Brannen
* @since 2.5
* @see AutowiredAnnotationBeanPostProcessor
* @see Qualifier
* @see Value
*/
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* <p>Defaults to {@code true}.
*/
boolean required() default true;
}
1、重点在注释里的一句:
Please consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}
2、AutowiredAnnotationBeanPostProcessor是Spring的后置处理器,专门处理@Autowired和@Value注解。查看AutowiredAnnotationBeanPostProcessor类,关注postProcessMergedBeanDefinition()方法、postProcessPropertyValues()方法和构造器;
//Spring在每个Bean实例化的时候,调用populateBean进行属性注入的时候,即调用postProcessPropertyValues方法。
@Deprecated
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
return postProcessProperties(pvs, bean, beanName);
}
//Spring容器在每个Bean实例化之后,调用AutowiredAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法。
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
//AutowiredAnnotationBeanPostProcessor构造器
public AutowiredAnnotationBeanPostProcessor() {
//后置处理器将处理@Autowire注解
this.autowiredAnnotationTypes.add(Autowired.class);
//后置处理器将处理@Value注解
this.autowiredAnnotationTypes.add(Value.class);
try {
//后置处理器将处理javax.inject.Inject JSR-330注解
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//获取指定类中autowire相关注解的元信息
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//对Bean的属性进行自动注入
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;
}
3、查看对Bean的属性进行自动注入metadata.inject(bean, beanName, 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()) {
for (InjectedElement element : elementsToIterate) {
element.inject(target, beanName, pvs);
}
}
}
4、查看element.inject(target, beanName, pvs);方法
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)throws Throwable {
if (this.isField) {
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
这是element.inject(target, beanName, pvs);的原始方法,它还有两个子类自己实现的方法,如图:
此案例是字段注入分析,查看AutowiredFieldElement
//AutowiredAnnotationBeanPostProcessor.java
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//获取要注入的字段
Field field = (Field) this.member;
Object value;
//如果字段的值有缓存
if (this.cached) {
//从缓存中获取字段值value
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 {
//核心!获取注入的值
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
//线程同步,确保容器中数据一致性
synchronized (this) {
//如果字段的值没有缓存
if (!this.cached) {
//字段值不为null,并且required属性为true
if (value != null || this.required) {
this.cachedFieldValue = desc;
//为指定Bean注册依赖Bean
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
//如果容器中有指定名称的Bean对象
if (beanFactory.containsBean(autowiredBeanName)) {
//依赖对象类型和字段类型匹配,默认按类型注入
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
//创建一个依赖对象的引用,同时缓存
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
}
//如果获取的依赖关系为null,且获取required属性为false
else {
//将字段值的缓存设置为null
this.cachedFieldValue = null;
}
//容器已经对当前字段的值缓存
this.cached = true;
}
}
}
//如果字段值不为null
if (value != null) {
//显式使用JDK的反射机制,设置自动的访问控制权限为允许访问
ReflectionUtils.makeAccessible(field);
//为字段赋值
field.set(bean, value);
}
}
从注解@Value/@Autowired中获取要注入的值,之后利用反射set到字段中。 重点就是怎么从注解中获取要注入的值,我们来看核心代码
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
//DefaultListableBeanFactory.java
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 Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
//真正获取值的代码
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
进行跟踪:
//DefaultListableBeanFactory.java
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
//获取字段属性的类型
Class<?> type = descriptor.getDependencyType();
//拿到@Value里的值
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
//如果标识@Autowired注解的属性是集合类型,Array,Collection,Map,
// 从这个方法获取@Autowired里的值
<1> Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//如果标识@Autowired注解的属性是非集合类型,
// 从这个方法获取@Autowired里的值
<2> Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
//如果没有符合该类型的Bean
if (matchingBeans.isEmpty()) {
//是否是必须的
if (isRequired(descriptor)) {
//抛出异常
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
//如果符合该类型的Bean有多个
if (matchingBeans.size() > 1) {
//挑选出最优解
<3> autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
//抛出异常
return descriptor.resolveNotUnique(type, matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
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;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
大致流程就是: 根据字段类型从IOC容器中获取符合的Bean,如果有多个,则挑选出最优的那一个。
<1>处:@Autowired注入集合数组,如Map.List。
<2>处:@Autowired注入非集合数组,即普通的类如Service
<3>处:多个同类型的bean中挑选出最优解
总结:文章来源:https://www.toymoban.com/news/detail-430772.html
在容器启动,为bean属性赋值的时候,spring会用后置处理器AutowiredAnnotationBeanPostProcessor解析@Autowired注解,来创建属性的实例,然后从IOC容器中根据@Primary、@Order、@PriorityOrder或Spring默认规则挑选出最符合的Bean,利用反射注入到字段中完成赋值;文章来源地址https://www.toymoban.com/news/detail-430772.html
到了这里,关于spring自动装配原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!