文章目录
- ①. Spring启动一行代码:
- ②. ApplicationContex增强功能
- ③. 自动装配如何装配进来
- ④. @Autowired自动注入细节xml版
- ⑤. @Autowired注解版分析
- ⑥. 总结一下
①. Spring启动一行代码:
- ①. 创建一个IOC容器,传入容器的xml配置文件,Spring在整个创建容器的过程中全部都准备好了,接下来就可以拿来用了
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
- ②.按照上面的Spring的架构原理图,ResourceReader先来加载Xml配置资源文件,加载来以后交给这些BeanDefinitionReaderBean的读取器来进行读取,这些BeanDefinitionReaderBean的读取器最终再交给BeanDefinitionParserDelegate解析器,来解析Xml配置资源文件中的每一个标签,如果Xml配置资源文件的标签里面是bean标签,说明是要生成一个组件,会为这个bean标签解析成一个BeanDefinition,这个BeanDefinitionbean定义信息就是造飞机的图纸,图纸最终进入档案馆BeanDefinitionRegistry,BeanDefinitionRegistry是一个接口,而真正的档案馆实现叫DefaultListableBeanFactory,DefaultListableBeanFactory档案馆里面最核心的关键点就在于beanDefinitionMap
//所有bean定义信息的集合,按照名字以及对应BeanDefinition关系都保存好了
// 这也解释了spring架构原理里面,spring解析来的所有资源都会存在这个档案馆,这个档案馆就是一个beanDefinitionMap
/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
- ③. 接下来就会看到源码里面会有一个for循环,从方案管里面获取bean定义的名字,挨个进行遍历,来进行获取和创建,这就是创建bean的过程
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
- ④. 整个bean又存储在DefaultSingletonBeanRegistry默认的单实例bean的注册中心,DefaultListableBeanFactory的最终父类还是DefaultSingletonBeanRegistry默认的单实例bean的注册中心,这也是默认的单实例bean中心
所有的单实例Bean都会在DefaultSingletonBeanRegistry这个里面
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {
- ⑤. DefaultSingletonBeanRegistry的具体哪个里面呢
- 整个Spring的设计都是模板方法模式,父类里面定义了很多方法属性,子类不断的去进行继承,子类来进行功能的增强。在DefaultSingletonBeanRegistry里面其中还有一个关键环节:singletonObjects
//缓存所有单实例bean对象,单例对象池,这也就是ioc容器-单例池
//Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
- 每一个对象,都有一个key(String),按照这个key(String)能够查到这个value(object)对象,这个对象就是单例对象池SingletonObjects.这个单例池(SingletonObjects)最终相当于按照图纸要造飞机一个真实的对象,造的飞机就在这个DefaultSingletonBeanRegistry,DefaultSingletonBeanRegistry是飞机的仓库,而DefaultSingletonBeanRegistry这个飞机仓库是DefaultListableBeanFactory这个的一个父类,Spring的底层只会用到DefaultListableBeanFactory这一个类,但这个DefaultListableBeanFactory一个类既是bean定义信息图纸的存储中心,又是DefaultSingletonBeanRegistry飞机的存储中心
- 在Spring底层,可以把单例对象池SingletonObjects称为容器,单例对象池SingletonObjects这里面是最常用的,所有的单实例都在单例对象池SingletonObjects这里面放着,所以这就是一个IOC容器
-
⑥. IOC容器其实在底层就是一个map - singletonObjects,把这些一大堆的组件保存起来,以后若要用,就直接从这个map - singletonObjects进行获取即可,这种设计模式叫享元模式(属于结构型模式)
享元模式:就是有一些东西后来要经常用,就可以把它池化,放在一个池里面,以后要用到的时候,直接返回它的元对象,享元就是返回元对象,所以这个享元模式就是一个很典型的模式,Spring最终把这些单例的东西放在这个SingletonObjects里面,以后谁要用就返回给谁,这也叫享元模式 -
⑦. 面试问,IOC容器是个啥?就说是一个享元模式实现的一个单例对象池singletonObjects,原来IOC容器的这个底层最应该关注的其实就是DefaultListableBeanFactory,这个DefaultListableBeanFactory有bean的定义信息,包括有整个Bean的真正实例信息等存在这里
②. ApplicationContex增强功能
- ①. 一个组件实现了ApplicationContextAware,就只需要准备一个ApplicationContext的Set方法。然后就会利用回调把ioc容器传入过来,这一块就相当于对这个组件的功能增强
/**
* Aware接口:装配spring底层的一些组件也就是bean工厂里面的东西
*/
@Component
public class Person implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//利用回调机制,把ioc容器传进来
this.context = applicationContext;
}
}
-
②. 一个Person为什么能把ApplicationContex这个ioc容器当为自己的参数传入进来?发现整个探索原理的过程中,Aware是什么时候创建过来的
-
③. 把档案馆里面每一个bean的名字获取到,然后每一个bean挨个创建
-
④. 创建的过程中就开始创建相应的对象,在整个相应对象创建完,初始化完了以后,就会执行一个东西叫BeanPostProcessor后置处理器这个东西也叫ApplicationContextAwareProcessor,ApplicationContextAwareProcessor实现了这个BeanPostProcessor后置处理器。
class ApplicationContextAwareProcessor implements BeanPostProcessor {
-
⑤. 初始化完以后,BeanPostProcessor后置处理器就会有一个执行所有这个处理器的回调,这个处理器执行回调的时候,就会判断当前正在初始化的这个对象,是不是ApplicationContextAware接口
-
⑥. 如果是这个ApplicationContextAware接口,它就把这个相应的对象,转成这个ApplicationContextAware接口,利用多态调用
-
⑦. 这个相应的对象转成ApplicationContextAware接口以后,就会调用ApplicationContextAware接口的setApplicationContextApplicationContext applicationContext方法,把ioc容器传进去,提供使用就行了,所以这就相当于自动注入了一个。不过这个对象是通过实现接口的方式进行自动注入的
-
⑧. 自动注入的这个东西的功能是由BeanPostProcessor后置处理器来进行完成的
③. 自动装配如何装配进来
- ①. 在Person里面把Car进行自动装配过来,在setCar方法的上面,标注一个@Autowired,相当于setCar方法就会被调用
/**
* Aware接口:装配spring底层的一些组件也就是bean工厂里面的东西
*/
@Component
public class Person implements ApplicationContextAware,MessageSourceAware {
// @Autowired
ApplicationContext context ; //可以要到ioc容器
public ApplicationContext getContext() {
return context;
}
public Person() {
System.out.println("person创建....");
}
private String name;
private Cat cat;
@Autowired
public void setCat(Cat cat) {
this.cat = cat;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//去容器中找,但是容器中的这个组件,是一个多实例的,所以一旦去了容器中找,
// 容器一看这个组件是多实例的,容器就应该给cat再创建一个实例
//@Lookup一定要放在get的方法上,因为@Bean的方式注册到容器中,那么@Lookup这个注解就不能用的
@Lookup
public Cat getCat() {
return cat;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//利用回调机制,把ioc容器传进来
this.context = applicationContext;
}
}
- ②. 在如下的三个位置打断点:Person默认的无参构造、setCat方法里面、setApplicationContext方法里面
- ③. 可以看到,来到了这个Person对象的创建的构造器
public Person() {
System.out.println("person创建....");
}
- ④. 放行后,到了setApplicationContext这个方法。这个方法是因为Person实现了ApplicationContextAware接口执行的,而它整个的执行逻辑就是这样:
- 想要创建ioc容器,ioc容器就得调用它自己的三参数的构造方法,然后在关键一步就得刷新它整个容器(refresh) new ClassPathXmlApplicationContext->refresh()
- refresh刷新容器的整个过程其实就是挨个进行创建组件,完成初始化,工厂的初始化就是把里面的所有东西都创建好 – finishBeanFactoryInitialization
- 创建所有非懒加载的单实例bean—preInstantiateSingletons
//(1). 想要创建ioc容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("xxx.xml");
//(2). ioc的三参构造方法
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
(3). 刷新工厂
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
// 刷新工厂
refresh();
}
}
(4). 完成Bean工厂初始化
refresh方法里面:
// Instantiate all remaining (non-lazy-init) singletons.
// 完成bean工厂的初始化,所以对象创建是在bean工厂初始化完成的时候干的事
finishBeanFactoryInitialization(beanFactory);
(5). 初始化所有的非懒加载的单实例bean
finishBeanFactoryInitialization方法里面:
// Instantiate all remaining (non-lazy-init) singletons.
//初始化所有的非懒加载的单实例bean
beanFactory.preInstantiateSingletons();
- 创建的过程就是如果你是工厂bean则执行下边逻辑isFactoryBean下面的逻辑,否则就执行getBean进行普通的单实例非懒加载bean的创建。下面为具体的细节:
preInstantiateSingletons下面的代码
// 从档案馆里面获取到所有的bean名称
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 如果是不是抽象 && 是单列 && 不是懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 如果是FactoryBean,就执行下边逻辑
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
// 若不是FactoryBean,就执行下面这段代码,普通的单实例非懒加载bean的创建
// Spring的底层bean第一次没有初始化,也是调用getBean这个方法来对bean进行初始化的
getBean(beanName);
}
}
}
//---------------------------------------------------------------------
// Implementation of BeanFactory interface
//---------------------------------------------------------------------
// getBean()相当于当前要初始化一个普通bean,那初始化这个普通bean就会调用doGetBean来执行这个getBean()方法,这就是一个典型的模板模式
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
// doGetBean里面有一个关键的环节叫创建bean的实例
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
.....
// 创建Bean实例 - Create bean instance.
if (mbd.isSingleton()) {
// bean实例它就会调用getSingleton方法
// getSingleton方法获取单例最核心的一点就是给这个方法里面传当前bean的名字,还传了一个lamdb表达式,而这个getSingleton方法接收的Lambda表达式叫ObjectFactory对象工厂
// 这个lamdb表达式相当于定义了一个函数式的接口,相当于Lambda表达式里面的内容就是getObject方法的方法体
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args); //创建bean对象的实例
}
});
}
@FunctionalInterface
public interface ObjectFactory<T> {
/**
* Return an instance (possibly shared or independent)
* of the object managed by this factory.
* @return the resulting instance
* @throws BeansException in case of creation errors
*/
T getObject() throws BeansException;
}
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
........
//这里会调用lamda表达式的内容
singletonObject = singletonFactory.getObject();
}
- 代码核心部分解释
5.1. createBean的官方注释也说明了,它是提供一个AbstractBeanFactory的实现,也就是这是一个抽象工厂的模板方法,所以这个模板方法模式在Spring底层也用的非常多
5.2. 它去调用真正的创建beancreateBean的方法,创建beancreateBean的方法是利用doCreateBean方法进行创建的,把bean的名字和bean的定义信息还把一些要用参数传了过来,但此时还没有bean的实例的
5.3. 整个bean的创建就有一个叫createBeanInstance的方法,这里它想要创建bean实例对象的时候就继续往下走,进入了createBeanInstance这个方法里面
5.4. 前面进行一大堆判断以后,主要就是为了拿到一个构造器ctors,然后前面若已经有构造器了,它可以用构造器进行自动注入autowireConstructor
5.5. 若没有这个构造器自动注入autowireConstructor就默认使用无参构造器instantiateBean:初始化bean为当前组件创建对象
AbstractAutowireCapableBeanFactory类下的
//---------------------------------------------------------------------
// Implementation of relevant AbstractBeanFactory template methods
//---------------------------------------------------------------------
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
......
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
......
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);//创建bean的实例
}
}
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
.....
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// 默认使用无参构造器为当前组件创建对象 No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
- 代码核心部分解释
6.1. 拿到初始化getInstantiationStrategy策略,就调用初始化instantiate方法
6.2. 初始化instantiate方法,就利用BeanUtils工具使用初始化策略来开始初始化,所以看Spring源码的底层,可以发现非常多的一些工具类。利用工具类将其进行赋值处理
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
// 这个初始化策略可以传入很多种初始化策略,一种是SimplelnstantiationStrategy使用JDK反射策略,另外一种是CglibSubclassingInstantiationStrategy使用Cglib创建一个代理对象策略
// 拿到初始化getInstantiationStrategy策略,就调用初始化instantiate方法
return getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
}, getAccessControlContext());
}
else {
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
....
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(beanDefinition, beanName, owner);
}
}
- ⑦. 经过上面① - ⑥最终相应的对象就创建好了,这就是对象创建,这是利用了初始化策略创建的bean实例。
相应的对象创建完了以后,那些组件是什么时候进来的?比如setApplicationContext是什么时候进来的?
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//利用回调机制,把ioc容器传进来
this.context = applicationContext;
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
try {
// 把当前bean里面的属性等该复制的复制,这个Bean的移民也就是牵扯到自动装配环节
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
-
⑦. 自动装配环节就是在populateBean这个方法里面,就是属性的赋值,Spring在什么时候搞定的
所有的bean都要进行以上这么一个大过程-每一个bean无非它要获取这个组件,获取的时候没有的时候就创建,创建完了对象有了接下来就属性赋值,属性赋值完了,就进行各种增强的环节 -
⑧. 继续来分析:什么时候发生了给相应属性进行赋值?
- 对象创建完以后,自然而然要属性赋值的操作,属性赋值就在populateBean这个方法里面
- populateBean这个方法前面封装了一个PropertyValues,就是从bean的定义信息里面拿到所有的属性键值对,而且这个PropertyValues还是个迭代器模式
- 相当于把当前bean里面有多少个属性,可以利用迭代器进行迭代出来,所以Spring里面又有一个迭代器模式叫PropertyValues,而每一个PropertyValues指的是属性的键值对,键就是属性名,值就是属性值
- 把深拷贝deepCopy这个里面的name,value信息拿来给bw,bw就相当于封装好了所有反射逻辑,所以至此这个bw方法一调用,那么底层就是各种反射进行设置值,把pvs这个相当于要赋值的这个玩意要给javabean里面设置过去,如果很多属性的话就是遍历赋值,所以这就是属性赋值过程
// (1). Initialize the bean instance.
Object exposedObject = bean;
try {
// 给创建好的对象每个属性进行赋值
populateBean(beanName, mbd, instanceWrapper);
// 初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
(2). populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
....
// PropertyValues指的是一个属性的键值对,键是属性名,value是属性值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
....
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
(3). applyPropertyValues
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
....
// Set our (possibly massaged) deep copy.
try {
// 这是一个深拷贝,拷贝真正的值,拷贝所有的值
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
(4).
@Override
public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
throws BeansException {
for (PropertyValue pv : propertyValues) {
setPropertyValue(pv);
}
- ⑨. 属性赋值了以后接下来还有一个叫初始化beaninitializeBean
(1). populateBean
try {
// 给创建好的对象每个属性进行赋值
populateBean(beanName, mbd, instanceWrapper);
// 初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
(2). applyBeanPostProcessorsBeforeInitialization
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
}
(3). postProcessBeforeInitialization
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 执行后置处理器逻辑
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
(4).invokeAwareInterfaces
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
bean instanceof ApplicationStartupAware)) {
return bean;
}
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
// 执行对应的处理器逻辑
invokeAwareInterfaces(bean);
}
return bean;
}
(5). 执行对应的处理器逻辑
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationStartupAware) {
((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
④. @Autowired自动注入细节xml版
理解过程即可
- ①. 坏境搭建、断点打在setCat方法上面
<bean class="com.xiaozhi.bean.Cat" id="cat">
<property name="name" value="TOMCAT"></property>
</bean>
-
②. 依旧还是那一套原理:还是创建IOC容器,IOC容器创建就调用三参数的构造器,然后要开始刷新工厂,要把所有里面的单实例组件都准备好,创建所有的非懒加载的单实例bean,然后调用getBean(beanName);,也就是每一个组件在容器底层都是调用getBean出来的,然后getBean里面继续doGetBean,然后继续调用lamda表达式的方法,然后前面已经创建好bean对象了…
-
③. 这里通过debug可以看到对应的属性值
- ④. 然后在这个环节就挨个遍历,给每一个属性进行赋值。
- ⑤, 当前cat要进行赋值,不过这个cat的值,已经拿到了,因为自动装配,它从容器中把这个值找到就行了。
调用writeMethod.invoke方法属性进行构造,最终还是利用反射调用setCat方法进行赋值
⑤. @Autowired注解版分析
-
①. 断点打在注解的方法里面
-
②. 原来的那一套流程,IOC创建,初始化所有单实例,getBean等一系列操作
-
③. 来到populateBean(beanName, mbd, instanceWrapper);给创建好的对象属性每个进行赋值
-
④. getBeanPostProcessorCache,相当于把所有的后置处理器的缓存拿来,相当于拿一些后置处理器。其中正在用的这个后置处理器叫AutowiredAnnotationBeanPostProcessor(自动装配注解的bean后置处理器)
如果是自动装配功能,还会使用一个后置处理器AutowiredAnnotationBeanPostProcessor
AutowiredAnnotationBeanPostProcessor后置处理器只不过接口叫InstantiationAwareBeanPostProcessor。
-
⑤. AutowiredAnnotationBeanPostProcessor这个后置处理器有了这个对象了,那么这个后置处理器拦截这个对象里面的加了注解的属性,给这些属性进行赋值,所以这也就是增强的拦截功能,在Spring的底层会发现非常多的这些后置处理器,在各个阶段来进行功能的增强
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 找到自动装配的元信息
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;
}
- ⑥. 找哪些属性或者方法上面使用了自动注入的注解
找所有属性的@Autowired和@Value,@Inject注解的
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);
}
// 下面是分析当前类方法或者属性有没有标注@Autowired等自动赋值的注解
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
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<>();
// (1). 找所有属性中标注了Autowired注解
ReflectionUtils.doWithLocalFields(targetClass, field -> {
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
// (2). 拿到所有的方法,看看有没有@Autowired注解
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;
}
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);
}
@Nullable
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
MergedAnnotations annotations = MergedAnnotations.from(ao);
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
MergedAnnotation<?> annotation = annotations.get(type);
if (annotation.isPresent()) {
return annotation;
}
}
return null;
}
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
- ⑦. 就是说它先找属性,再找方法看有没有标注@Autowired注解的。只要找到了就加入到元素里面,最终所有都找到以后,把所有的这些元素elements进行返回,一返回以后,就相当于要@Autowired自动装配的东西
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);
}
}
}
- ⑧. 最后利用反射赋值就来到了setCat方法
⑥. 总结一下
Spring的底层通过后置增强机制来完成很多功能,所有后来的核心功能,比如切面,比如事务,比如代理,日志等一大堆,一个注解就能够搞定的事情,这到底它是怎么完成的?所以要分析Spring的一个功能的时候,主要分析两点就行了:
1. 这个功能Spring在启动的时候注入了什么组件?比如想做事务相关,Spring在启动就会准备一个事务的TransactionManager事务管理器
2. 这个功能牵扯到的组件在什么位置被什么后置增强器增强成了什么样子
这是复习回顾顺便研究了一下BeanPostProcessor后置处理器整个强大之处,BeanPostProcessor翻译过来就是bean的后置处理器,它就是在一个bean的初始化前后进行的功能增强的作用,但是这个BeanPostProcessor处理器有很多的子接口,所有这些个后置处理器何时进行了增强,就是Spring源码之后置处理器的接口关系和Spring源码之工厂的后置处理&配置类处理以及Spring源码之bean后置处理器的创建过程研究的重点,如果把这些研究好了,那么在后来分析Spring的任何功能也就非常简单了