創(chuàng)新互聯(lián)專注于企業(yè)全網(wǎng)整合營銷推廣、網(wǎng)站重做改版、阜康網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、html5、商城開發(fā)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為阜康等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
該趟專車是開往Spring Boot自動(dòng)注入原理源碼分析的專車
public interface PersonService {
String hello(String name);
}
@Service(value = "studentService")
public class StudentServiceImpl implements PersonService {
@Override
public String hello(String name) {
return "[student service] hello " + name;
}
}
@Service(value = "teacherService")
public class TeacherServiceImpl implements PersonService {
@Override
public String hello(String name) {
return "[teacher service] hello " + name;
}
}
@RestController
public class TestController {
@Autowired
private PersonService studentService;
@Autowired
private PersonService teacherService;
@GetMapping("/hello")
public String hello(@RequestParam(name = "name") String name) {
return studentService.hello(name) + "=======>" + teacherService.hello(name);
}
}
以上示例代碼很簡單,創(chuàng)建了一個(gè)接口,接口有兩個(gè)實(shí)現(xiàn)類,然后在控制器中注入實(shí)現(xiàn)類,從而完成業(yè)務(wù)方法的調(diào)用。接下來我們就開始對(duì)源碼進(jìn)行分析
在分析代碼之前我們先回憶一下操作對(duì)象的步驟:
有了上面的基礎(chǔ)知識(shí),接下來就開始揭秘旅程
在分析源碼的時(shí)候最關(guān)鍵的一步就是尋找程序的入口,有了入口我們就成功了一半,那么如何尋找程序的入口?針對(duì)此處的源碼分析,我們可以在TestController類上打一個(gè)斷點(diǎn),然后查看調(diào)用鏈
基于調(diào)用鏈路,我們看到有一個(gè)doCreateBean方法,該方法就是用來創(chuàng)建bean的,也就是我們上面提到的實(shí)例化對(duì)象部分
AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 創(chuàng)建bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
// ...省略部分代碼
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 填充bean,也就是我們上面提到的調(diào)用對(duì)象的set方法設(shè)置對(duì)象屬性
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
// ...省略部分代碼
return exposedObject;
}
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// ...省略代碼
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
// 遍歷所有的后置處理器
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 通過斷點(diǎn)分析我們可以得知此處調(diào)用的是AutowiredAnnotationBeanPostProcessor#postProcessProperties
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
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);
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
AutowiredAnnotationBeanPostProcessor#postProcessProperties
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 查找當(dāng)前bean需要注入的元數(shù)據(jù)信息,以TestController為例,那么需要注入的就是studentService和teacherService兩個(gè)屬性
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;
}
注入屬性 AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// 獲取屬性,此處的屬性就是studentService
Field field = (Field) this.member;
// 屬性對(duì)應(yīng)的value
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 {
// 解析屬性依賴
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;
}
}
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
// 給屬性設(shè)置值,完成注入功能
field.set(bean, value);
}
}
解析屬性依賴 DefaultListableBeanFactory#resolveDependency
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;
}
}
解析屬性依賴 DefaultListableBeanFactory#doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// ...省略代碼
// 解析多個(gè)Bean,比如Array、List、Map類型,有興趣可以自己查看分析
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 根據(jù)類型獲取候選對(duì)象,針對(duì)studentService而言,該屬性的類型為PersonService
// PersonService有2個(gè)實(shí)現(xiàn)類,StudentServiceImpl和TeacherServiceImpl
// 所以此處獲取結(jié)果為StudentServiceImpl對(duì)象和TeacherServiceImpl對(duì)象
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 重點(diǎn)處理,如果存在多個(gè)匹配的bean
if (matchingBeans.size() > 1) {
// 從已經(jīng)匹配的bean中選擇一個(gè)符合的bean
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
// 如果bean必須注入或者存在多個(gè)匹配的bean,則拋出異常
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), 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;
}
}
// 根據(jù)bean名稱獲取對(duì)應(yīng)的示例
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());
}
// 返回對(duì)應(yīng)的示例對(duì)象
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
此處主要根據(jù)類型獲取所有匹配的bean,如果匹配的bean有多個(gè),那么最后會(huì)選擇一個(gè)符合條件的bean名稱,然后將對(duì)應(yīng)的bena實(shí)例返回,調(diào)用set方法進(jìn)行進(jìn)行注入,到此注入的原理本該結(jié)束了。但是還是要分析一下Spring Boot是如何選擇出符合條件的bean?
選擇符合條件的bean DefaultListableBeanFactory#determineAutowireCandidate
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
// 如果bean對(duì)應(yīng)的primary屬性為true,則返回bean對(duì)應(yīng)的名稱
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
// 如果候選bean使用javax.annotation.Priority標(biāo)注,返回高優(yōu)先級(jí)bean對(duì)應(yīng)的名稱
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
// 如果匹配bean的名稱和需要注入的屬性名稱一致,則返回匹配bean的名稱
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
獲取符合條件bean名稱總結(jié):
回顧一下開頭的2個(gè)問題:
第一個(gè)問題:是在Bean實(shí)例化后,填充Bean的時(shí)候注入@Autowired標(biāo)注的屬性
第二個(gè)問題:如果存在多個(gè)類型的Bean,會(huì)根據(jù)primary--->javax.annotation.Priority--->名稱依次過濾,得到最終匹配的bean名稱
分享題目:原創(chuàng)001|搭上SpringBoot自動(dòng)注入源碼分析專車
本文來源:http://www.rwnh.cn/article8/igpsop.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、網(wǎng)站維護(hù)、App設(shè)計(jì)、網(wǎng)站導(dǎo)航、服務(wù)器托管、云服務(wù)器
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)