接上一節内容,分析依賴注入和屬性填充
貼上測試代碼:
@Component
//@Order(2)
public class Test {
public String test = "test";
}
@Component
public class UserService implements InitializingBean, BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware, EmbeddedValueResolverAware , ApplicationContextAware {
@Autowired
private Test test;
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("BeanNameAware.afterPropertiesSet()-------------");
}
public void test() {
System.out.println("test");
}
@Override
public void setBeanName(String name) {
System.out.println("----BeanClassLoaderAware.setBeanClassLoader---");
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("----BeanClassLoaderAware.setBeanClassLoader---");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("----BeanFactoryAware.setBeanFactory---");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("----EnvironmentAware.setApplicationContext---");
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
System.out.println("----EmbeddedValueResolverAware.setEmbeddedValueResolver----");
}
@Override
public void setEnvironment(Environment environment) {
System.out.println("----ApplicationContextAware.setEnvironment----");
}
}
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
// TestBeanFactoryPostProcessor testBeanFactoryPostProcessor = new TestBeanFactoryPostProcessor();//要在執行個體化之前加入,還沒找到怎麼加入
// applicationContext.addBeanFactoryPostProcessor(testBeanFactoryPostProcessor);
UserService userService = applicationContext.getBean("userService", UserService.class);
userService.test();
}
}
我們的目的就是UserService中的
@Autowired
private Test test;
是什麼時候注入的,是怎麼注入的。
總之Spring在屬性填充的時候,首先會去尋找注入點,然後根據注入點進行注入。
1.Spring 尋找注入點(@AutoWried @Resource @Value)
根據上一節的doCreateBean方法源碼開始:
doCreateBean方法屬性填充是在這一段
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 運作修改合并好了的BeanDefinition
// 這裡會查找@Autowired的注入點(InjectedElement),并把這些注入點添加到mbd的屬性externallyManagedConfigMembers中
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 如果目前建立的是單例bean,并且允許循環依賴,并且還在建立過程中,那麼則提早暴露
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");
}
// 此時的bean還沒有完成屬性注入,是一個非常簡單的對象
// 構造一個對象工廠添加到singletonFactories中
// 第四次調用後置處理器
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); // AService
}
// Initialize the bean instance.
// 對象已經暴露出去了
Object exposedObject = bean;
try {
// 3、填充屬性 @Autowired
populateBean(beanName, mbd, instanceWrapper); //
// 4、 初始化 和 BeanPostProcessor 正常AOP BeanPostProcessor
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
第一段代碼非常重要
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 運作修改合并好了的BeanDefinition
// 這裡會查找@Autowired的注入點(InjectedElement),并把這些注入點添加到mbd的屬性externallyManagedConfigMembers中
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
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源碼:
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
/**
* Post-process the given merged bean definition for the specified bean.
* @param beanDefinition the merged bean definition for the bean
* @param beanType the actual type of the managed bean instance
* @param beanName the name of the bean
* @see AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
*/
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
/**
* A notification that the bean definition for the specified name has been reset,
* and that this post-processor should clear any metadata for the affected bean.
* <p>The default implementation is empty.
* @param beanName the name of the bean
* @since 5.1
* @see DefaultListableBeanFactory#resetBeanDefinition
*/
default void resetBeanDefinition(String beanName) {
}
}
這個接口也是繼承BeanPostProcessor,是以也有該接口的功能。
這段代碼其實非常簡單,其實就是判斷BeanFactory裡面的beanPostProcessors是否有存在MergedBeanDefinitionPostProcessor類型的接口,然後調用MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)
現在我們來看這段代碼都做了什麼
利用debug模式打上條件斷點
然後看一下BeanFactory裡面的beanPostProcessors有幾個後置處理器:
兩個是自己加入的,其餘的是Spring 啟動的時候自己加入的(有幾個特别熟悉有沒有,在第一節我已經講過了)
符合bp instanceof MergedBeanDefinitionPostProcessor 的有:
1.CommonAnnotationBeanPostProcessor
2.AutowiredAnnotationBeanPostProcessor
3.AnnotationConfigApplicationContext
再看這個幾個類的postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)都做了什麼:
1.CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName):
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
進入
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
metadata.checkConfigMembers(beanDefinition);
}
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
if (this.lifecycleMetadataCache == null) {
// Happens after deserialization, during destruction...
return buildLifecycleMetadata(clazz);
}
// Quick check on the concurrent map first, with minimal locking.
LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
synchronized (this.lifecycleMetadataCache) {
metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
metadata = buildLifecycleMetadata(clazz);
this.lifecycleMetadataCache.put(clazz, metadata);
}
return metadata;
}
}
return metadata;
}
由上可知這個方法就是查詢父類的中繼資料資訊LifecycleMetadata。
我們在來他是怎麼拿出父類的資訊的,進入metadata = buildLifecycleMetadata(clazz);
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
return this.emptyLifecycleMetadata;
}
List<LifecycleElement> initMethods = new ArrayList<>();
List<LifecycleElement> destroyMethods = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
}
}
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
currDestroyMethods.add(new LifecycleElement(method));
if (logger.isTraceEnabled()) {
logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
}
}
});
initMethods.addAll(0, currInitMethods);
destroyMethods.addAll(currDestroyMethods);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
關鍵點:
targetClass = targetClass.getSuperclass();
while (targetClass != null && targetClass != Object.class);
其實就是一直循環取父類直到為null 和targetClass != Object.class(有空來測試繼承的情況)
這裡還有一個點就是:
AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType)
@Nullable
private Class<? extends Annotation> initAnnotationType;
@Nullable
private Class<? extends Annotation> destroyAnnotationType;
很直覺的了解到,該方法還會去尋找初始方法和銷毀方法存入到LifecycleMetadata,也就是标注@PostConstruct和@PreDestroy的方法。
繼續往下面走:
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
metadata = buildResourceMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
ReflectionUtils.doWithLocalFields(targetClass, field -> {
if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
}
currElements.add(new WebServiceRefElement(field, field, null));
}
else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static fields");
}
currElements.add(new EjbRefElement(field, field, null));
}
else if (field.isAnnotationPresent(Resource.class)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static fields");
}
if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
currElements.add(new ResourceElement(field, field, null));
}
}
});
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
}
else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new EjbRefElement(method, bridgedMethod, pd));
}
else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static methods");
}
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1) {
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
}
if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new ResourceElement(method, bridgedMethod, pd));
}
}
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
也是循環去找父類的@Resource注入點(字段和方法)還有幾個if else暫時不知道。
總而言之:
(1)該方法的主要作用是找出父類的LifecycleMetadata和标注@PostConstruct和@PreDestroy的方法注入點。
(2)找出字段和方法的@Resource注入點等一些操作。
2.AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName):
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 擷取beanType中的注入點
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
// 尋找目前clazz中的注入點,把所有注入點整合成為一個InjectionMetadata對象
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
// 判斷是不是候選者類,比如說類名,如果是以"java."開頭的則不是候選者類
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 周遊屬性,看是否有@Autowired,@Value,@Inject注解
ReflectionUtils.doWithLocalFields(targetClass, field -> {
//
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
// 如果存在@Autowired,@Value,@Inject注解其中一個
if (ann != null) {
// 如果字段是static的,則直接進行傳回,不進行注入
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 是否required
boolean required = determineRequiredStatus(ann);
// 生成一個注入點AutowiredFieldElement
currElements.add(new AutowiredFieldElement(field, required));
}
});
// 周遊方法,看是否有@Autowired,@Value,@Inject注解
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
// 靜态方法不能用來注入屬性
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
// 方法參數值為0,不能用來注入屬性
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
// 根據方法找出對應的屬性
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
// 所有能夠注入的屬性集合
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
其實從
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata = buildAutowiringMetadata(clazz);
就可以看出就是在找@Autowire的注入點,但是值得注意得是還在找@Value的注入點(方法和字段,方法參數為0的時候不用來注入),當然也是循環也找父類的注入點。關鍵代碼如下:
AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
targetClass = targetClass.getSuperclass();
while (targetClass != null && targetClass != Object.class);
總而言之:該方法是尋找目前類及父類标注@Autowire和@Value的注入點(字段和方法)
3.AnnotationConfigApplicationContext.postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName):
// 執行個體化之後,填充屬性之前會執行,會把某個ApplicationListener的bean的名字添加到singletonNames中去
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if (ApplicationListener.class.isAssignableFrom(beanType)) {
this.singletonNames.put(beanName, beanDefinition.isSingleton());
}
}
這個方法就不做過多解釋了。
2.上面已經找到注入點了,下面我們來分析怎麼注入的
直接F8跳到:
// 3、填充屬性 @Autowired
populateBean(beanName, mbd, instanceWrapper);
進入該方法,該方法裡面有一段:
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 調用BeanPostProcessor分别解析@Autowired、@Resource、@Value,得到屬性值
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;
}
}
}
有沒有非常熟悉,其實主要的目的是周遊BeanFactory裡面的BeanPostProcessors,然後判斷
bp instanceof InstantiationAwareBeanPostProcessor
調用InstantiationAwareBeanPostProcessor.postProcessProperties方法,我們在看各個InstantiationAwareBeanPostProcessor都做了什麼
1.CommonAnnotationBeanPostProcessor.postProcessProperties:
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
}
return pvs;
}
很直覺的了解到,這是對父類的屬性注入,還解析@Resource注入點注入:
@Override
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
getResource(this, requestingBeanName));
}
protected Object getResource(LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
if (StringUtils.hasLength(element.mappedName)) {
return this.jndiFactory.getBean(element.mappedName, element.lookupType);
}
if (this.alwaysUseJndiLookup) {
return this.jndiFactory.getBean(element.name, element.lookupType);
}
if (this.resourceFactory == null) {
throw new NoSuchBeanDefinitionException(element.lookupType,
"No resource factory configured - specify the 'resourceFactory' property");
}
return autowireResource(this.resourceFactory, element, requestingBeanName);
}
protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
Object resource;
Set<String> autowiredBeanNames;
String name = element.name;
if (factory instanceof AutowireCapableBeanFactory) {
AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
DependencyDescriptor descriptor = element.getDependencyDescriptor();
if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
autowiredBeanNames = new LinkedHashSet<>();
resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
if (resource == null) {
throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
}
}
else {
resource = beanFactory.resolveBeanByName(name, descriptor);
autowiredBeanNames = Collections.singleton(name);
}
}
else {
resource = factory.getBean(name, element.lookupType);
autowiredBeanNames = Collections.singleton(name);
}
if (factory instanceof ConfigurableBeanFactory) {
ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;
for (String autowiredBeanName : autowiredBeanNames) {
if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) {
beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName);
}
}
}
return resource;
}
繼續往下面走:
2.AutowiredAnnotationBeanPostProcessor.postProcessProperties
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// InjectionMetadata中儲存了所有被@Autowired注解标注的屬性/方法并封裝成一個個的InjectedElement
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;
}
// InjectionMetadata中儲存了所有被@Autowired注解标注的屬性/方法并封裝成一個個的InjectedElement
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
這些注入點從哪裡來,不就是從上面合并出來的嘛
再次進入inject()方法:
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) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
// element可能是Method,也可能是Field
element.inject(target, beanName, pvs);
}
}
}
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
// 目前注入點已經注入過了,有緩存了,則利用cachedFieldValue去找對應的bean
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
// Spring在真正查找屬性對應的對象之前, 會先将該屬性的描述封裝成一個DependencyDescriptor, 裡面儲存了Filed、是否強制需要即required, 以及屬性所在的類(即Field所在的類Class對象)
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 {
// 根據field去尋找合适的bean
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;
// 注冊目前bean依賴了哪些其他的bean的name
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);
field.set(bean, value);
}
}
}
這個方法就是确定一個唯一的注入點确定值,有可能找到的是類,則需要
beanFactory.getBean(beanName);建立bean對象
然後通過反射的方式設定進去
這裡面存在一個問題就是,如何确定一個唯一的值,其實在DefaultListableBeanFactory工廠裡面有一個protected String determineAutowireCandidate(Map candidates, DependencyDescriptor descriptor)方法:
@Nullable
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
// 取@Primary的bean
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
// 取優先級最高的bean 通過@Priority來定義優先級,數字越小,優先級越高
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
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;
}
裡面有注釋可以自行觀看
其實該方法就是先去根據@Primary的bean确定唯一值,然後取優先級最高的bean 通過@Priority來定義優先級,數字越小,優先級越高,最後根據屬性名來确定。
3.對于自己重寫的InstantiationAwareBeanPostProcessor.postProcessProperties造成什麼樣的結果後續分析
總結:
1.通過内置的MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition方法尋找注入點
2.然後過内置InstantiationAwareBeanPostProcessor.postProcessProperties的方法進行屬性注入。
補充一個知識點:
父子BeanDefinition
父子BeanDefinition是Spring中的概念,Spring在根據BeanDefinition建立Bean的過程中,會先看目前BeanDefinition是否存在父BeanDefinition,如果存在則需要進行合并,合并就是把子BeanDefinition和父BeanDefinition中所定義的屬性整合起來(如果存在某個屬性在父子BeanDefinition中都存在,那麼取子BeanDefinition中的屬性)
網上找到的一個例子:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="parent" abstract="true"
class="com.dmz.official.merge.TestBean">
<property name="name" value="parent"/>
<property name="age" value="1"/>
</bean>
<bean id="child"
class="com.dmz.official.merge.DerivedTestBean"
parent="parent" >
<property name="name" value="override"/>
</bean>
</beans>
public class DerivedTestBean {
private String name;
private int age;
// 省略getter setter方法
}
public class TestBean {
private String name;
private String age;
// 省略getter setter方法
}
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext cc = new ClassPathXmlApplicationContext("application.xml");
DerivedTestBean derivedTestBean = (DerivedTestBean) cc.getBean("child");
System.out.println("derivedTestBean的name = " + derivedTestBean.getName());
System.out.println("derivedTestBean的age = " + derivedTestBean.getAge());
}
}