getBean(String beanName)是spring的核心方法
--->doGetBean:其中transformedBeanName是处理beanName的;getSingleton是从缓存中的bean单例;getObjectForBeanInstance是当bean是factoryBean的时候,调用其getObejct方法返回实例;dependsOn是实例化当前bean之前,要实例化所依赖的bean;接下来就是单例、多例、自定义scope的处理,单例和多例的不同在于单例用的getSingleton方法中有对singletonObjects加同步锁,从缓存中获取。
--->getSingleton:对singletonObjects加锁,在创建bean之前调用beforeSingletonCreation把beanName放到singletonsCurrentlyInCreation中,调用createBean创建bean,调用afterSingletonCreation把beanName从singletonsCurrentlyInCreation中移除,调用addSingleton方法把bean放到singletonObjects中,从singletonFactories和singletonFactories的两个缓存中移除beanName。
--->createBean:prepareMethodOverrides;resolveBeforeInstantiation是在bean被实例化之前,调用BeanPostProcessor的子类InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法生成bean,如果bean不为null再调用applyBeanPostProcessorsAfterInitialization进行初始化之后的处理。AOP这种动态代理就是在这里应用的。注意Instantiation--实例化和Initialization--初始化的区别,前者是调用构造方法生成bean,后者是调用invokeInitMethods方法初始化bean;如果所有的InstantiationAwareBeanPostProcessor都没有提前生成bean,那么进入doCreateBean。
--->doCreateBean:核心是createBeanInstance调用构造方法生成bean实例;earlySingletonExposure是判断要不要在给属性赋值前放入singletonFactories,这是单例生成时避免循环引用的关键;populateBean先调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法、postProcessProperties方法、postProcessPropertyValues方法(autowired注解的的处理就是在这里);initializeBean的invokeAwareMethods方法是看bean有没有实现BeanNameAware,BeanClassLoaderAware,BeanFactoryAware等接口。applyBeanPostProcessorsBeforeInitialization中执行BeanPostProcessor的postProcessBeforeInitialization。invokeInitMethods中判断如果bean实现了InitializingBean接口,执行afterPropertiesSet方法,再执行@Bean注解中InitMethod指向的方法;
1、getBean(Class beanType)--->resolveBean--->resolveNamedBean遍历所有beanDefinition,找到所有符合beanType的beanName,再根据priority和order挑选优先级最高的那个beanName,调用getBean(String beanName)方法得到bean
2、构造方法注入:在上面的doCreateBean---createBeanInstance方法中,先挑选构造方法,如果挑选出来的构造方法是有参数的,参数是要按照类型去找bean注入的,逻辑是determineConstructorsFromBeanPostProcessors--->SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors,其中起作用的是AutowiredAnnotationBeanPostProcessor,点进去看, @autowired注解的构造器(只能有一个)>无参构造器>有参构造器(只能有一个),反射调用构造方法的时候,要传入参数,beanFactory.autowireConstructor --->new ConstructorResolver(this).autowireConstructor--->argsHolder = createArgumentArray--->autowiredArgument = resolveAutowiredArgument--->this.beanFactory.resolveDependency--->doResolveDependency,先处理@Value注解,resolveMultipleBeans处理collection类型的注入,不是collection类型的用findAutowireCandidates--->addCandidateEntry获取所有当前类型的beanName - beanClass根据isAutowireCandidate方法判断真假,放到matchingBeans中,而isAutowireCandidate中会调用QualifierAnnotationAutowireCandidateResolver.isAutowireCandidate处理@Qualifier注解。如果matchingBeans的size > 1,determineAutowireCandidate根据优先级决定唯一一个beanName,再调用descriptor.resolveCandidate--->beanFactory.getBean(beanName),可见最后还是getBean(String beanName)这个方法。
3、@Autowired注解(属性上或者方法上):上面说的doCreateBean中,AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues--->postProcessProperties--->metadata.inject-->element.inject/这里的element包含field和method,以field为例,还是value = beanFactory.resolveDependency,逻辑和上面构造方法注入是一样的。@resource注解的处理是CommonAnnotationBeanPostProcessor
4、bean实例化之后的初始化处理:已知在上面说的doCreateBean方法中,先处理@PostConstruct,再执行afterPropertiesSet然后执行InitMethod,@PostConstruct的处理是在InitDestroyAnnotationBeanPostProcessor的postProcessBeforeInitialization方法,具体:findLifecycleMetadata---buildLifecycleMetadata检测方法上有没有initAnnotationType,这个initAnnotationType在子类CommonAnnotationBeanPostProcessor的构造方法里面被设置成PostConstruct.class。有的话收集起来,执行metadata.invokeInitMethods。
5、循环引用的思考:我们讨论单例模式的时候,直接加同步锁再判断有没有缓存是最粗暴但是也是最直接的一个方法了,既然都已经加锁了,那么beforeSingletonCreation和afterSingletonCreation两个方法中的singletonsCurrentlyInCreation这个map是做什么用的?回顾单例的生成:先去缓存里面找,没有的话去创建,在构造方法执行之后,给引用属性赋值之前,把单例放到缓存中,这样哪怕接下来给引用赋值的时候遇到循环引用的时候,也能从缓存中找到了。但是注意,如果是构造方法中的引用赋值导致的循环引用,此时当前单例并没有放到缓存中,就会出现循环引用形成多个bean导致单例模式失效。singletonsCurrentlyInCreation就是防止这种现象的:beforeSingletonCreation方法在构造方法之前,如果构造方法中出现循环引用,发现缓存中没有当前单例,就会再调用getBean,再次进入 beforeSingletonCreation,就会发现已经有这个beanName了,从而报错。
6、单例是谁的单例?beanName是单例bean在Spring工厂的唯一标志,当然根据beanType每次注入,根据筛选如果能做到同一个对象,所以从这个意义上也可以说beanType。
7、@lazy注解:第一种用法是和@Autowired一起注解在属性或者方法或者构造方法的参数前面,根据前面的逻辑,这个是注入的时候要处理的事情,由于构造方法和属性方法注入都是经过beanFactory.resolveDependency,点进去看,在进入doResolveDependency之前会有Optional、ObjectFactory、ObjectProvider、Provider以及@lazy的处理,这几种的处理基本上都是用动态代理先返回一个代理类,等真正使用的时候再调用doResolveDependency获取bean,顺便说一句,springcloud的1.5.X的版本就是用provider的方式在ribbon那里获取eurekaClient。第二种用法是和@Component一起注解在配置类或和@Bean一起注解在方法上,这样当beanFactory的refresh最后把所有单例的beanDefinition都实例化到工厂的时候,就会放过这个注解了@lazy的bean。
8、factoryBean:在doGetBean方法中,不管是从缓存中取单例,还是生成单例、多例等,在后面都有getObjectForBeanInstance方法,意思是当前bean如果是FactoryBean类型的,不能直接返回,要调用它的getObject方法返回。往远一点说,factoryBean类型的beanDefinition能被自动注入是在findAutowireCandidates--->BeanFactoryUtils.beanNamesForTypeIncludingAncestors--->getBeanNamesForType--->doGetBeanNamesForType--->isTypeMatch--->getTypeForFactoryBean--->factoryBean.getObjectType() 。
9、factoryMethod:和factoryBean是两个层面的逻辑,在上面的2的createBeanInstance中,在寻找构造方法生成bean之前,会判断当前的beanDefinition有没有factoryMethod,如果有,就优先使用factoryMethod。springboot的@Bean注解就是用到了factoryMethod。