為了搞明白自動裝配原理,需要知道spring容器管理bean的生命周期
Spring Bean 生命周期流程圖
bean自身方法的生命周期
分為四步:
//執(zhí)行此段代碼,spring容器的bean執(zhí)行實例化、屬性賦值、初始化
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//關閉容器,執(zhí)行銷毀
classPathXmlApplicationContext.close();
1、實例化
- 讀取spring配置文件
- 通過反射進行bean的實例化(eg:通過BeanFactory實例化)
2、屬性賦值
- 解析自動裝配(byName、byType、constractor、default)DI的體現(xiàn)
- 循環(huán)依賴
3、初始化
- 調用XXXAware回調方法
- 調用初始化生命周期回調(三種)
- 如果bean實現(xiàn)aop創(chuàng)建動態(tài)代理
4、銷毀
- 在spring容器關閉的時候進行調用
- 調用初始化生命周期回調
對應上述文字,下圖展示了bean裝載到spring應用上下文種的一個典型的生命周期過程
@Autowired注解的自動裝配過程
先說結論:
@Autowired是在Bean屬性賦值階段進行裝配,通過Bean的后置處理器進行解析
1、在創(chuàng)建一個spring上下文的時候在構造函數(shù)中注冊AutowiredAnnotationBeanPostProcessor
2、在Bean的創(chuàng)建過程中進行解析
? ? ? ? 1、在實例化后預解析(解析@Autowired標注的屬性、方法,比如:把屬性的類型、名稱、屬性所在的類...元數(shù)據(jù)緩存)
? ? ? ? 2、在屬性賦值階段真正的注入(拿到上一步緩存的元數(shù)據(jù)去ioc容器進行查找,并且返回注入)
????????????????a.首先根據(jù)解析的元數(shù)據(jù)拿到類型去容器種查找
? ? ? ? ? ? ? ? ? ? ? ? *如果查詢結果剛好為一個,就將該bean裝配給@Autowired指定的數(shù)據(jù);
????????????????????????*如果查詢的結果不止一個,那么@Autowired會根據(jù)名稱來查找
????????????????????????*如果上述查找結果為空,那么就會拋出異常。
大致流程圖如下:
?@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);的原始方法,它還有兩個子類自己實現(xiàn)的方法,如圖:
?此案例是字段注入分析,查看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 {
//創(chuàng)建一個字段依賴描述符
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);
}
//線程同步,確保容器中數(shù)據(jù)一致性
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())) {
//創(chuàng)建一個依賴對象的引用,同時緩存
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) {
//挑選出最優(yōu)解
<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);
}
}
大致流程就是: 根據(jù)字段類型從IOC容器中獲取符合的Bean,如果有多個,則挑選出最優(yōu)的那一個。
<1>處:@Autowired注入集合數(shù)組,如Map.List。
<2>處:@Autowired注入非集合數(shù)組,即普通的類如Service
<3>處:多個同類型的bean中挑選出最優(yōu)解
總結:文章來源:http://www.zghlxwxcb.cn/news/detail-430772.html
????????在容器啟動,為bean屬性賦值的時候,spring會用后置處理器AutowiredAnnotationBeanPostProcessor解析@Autowired注解,來創(chuàng)建屬性的實例,然后從IOC容器中根據(jù)@Primary、@Order、@PriorityOrder或Spring默認規(guī)則挑選出最符合的Bean,利用反射注入到字段中完成賦值;文章來源地址http://www.zghlxwxcb.cn/news/detail-430772.html
到了這里,關于spring自動裝配原理的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!