当前位置: 首页 > 科技观察

Spring源码中Bean实例化的基本原理

时间:2023-03-13 03:29:09 科技观察

创建SpringBean实例化是SpringBean生命周期的第一阶段Bean的生命周期主要有以下几个步骤:《详细介绍:SpringInAction是这样说的:》例子转换Bean对象。这时候的Bean对象是很底层的,基本不能被我们使用,因为连最基本的属性都没有设置。可以理解为连Autowired注解都不解析;当属性填好后,这一步就完成了,Bean对象就基本完成了。可以理解为Autowired注解已经解析完成,依赖注入完成;如果Bean实现了BeanNameAware接口,则调用setBeanName方法;如果Bean实现了BeanClassLoaderAware接口,则调用setBeanClassLoader方法;如果Bean实现了BeanFactoryAware接口,则调用setBeanFactory方法;调用BeanPostProcessor的postProcessBeforeInitialization方法;如果Bean实现了InitializingBean接口,则调用afterPropertiesSet方法;如果Bean定义了init-method方法,则调用Bean的init-method方法;当到达这一步时,Bean就准备好了,并停留在应用程序的上下文中,直到它被销毁;如果应用程序的上下文被销毁,如果Bean实现了DisposableBean接口,则调用destroy方法,如果Bean定义了destroy-method,声明也会调用destroy方法。在实例化Bean之前,BeanDefinition中已经有了所有需要实例化的元数据,接下来Spring只需要选择合适的实例化方式和策略即可。《BeanDefinition》Spring容器启动时,会定位到我们的配置文件,加载该文件,解析成Bean定义文件。BeanDefinition右边的Map存放了bean之间依赖关系的定义。BeanDefinition,例如OrderController依赖于OrderService的实例化,有两种方法:工厂方法和构造函数实例化,后者是最常见的。其中,Spring默认的实例化方式是无参构造函数实例化。比如xml中定义的注解标注的bean,都是通过默认的实例化方法“实例化静态工厂方法”publicclassFactoryInstance{publicFactoryInstance(){System.out.println("instancebyFactoryInstance");}}publicclassMyBeanFactory{publicstaticFactoryInstancegetInstanceStatic(){returnnewFactoryInstance();}}"Instantiationusinginstancefactorymethod"publicclassMyBeanFactory{/***实例工厂创建bean实例**@return*/publicFactoryInstancegetInstance(){returnnewFactoryInstance();}}「使用无参构造函数实例化(默认的)」publicclassConstructorInstance{publicConstructorInstance(){System.out.println("ConstructorInstancenoneargs");}}「使用有参与构造函数实例化」publicclassConstructorInstance{privateStringname;publicConstructorInstance(Stringname){System.out.println("ConstructorInstancewithargs");this.name=name;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}}源码阅读直接看下AbstractAutowireCapableBeanFactory类中doCreateBean方法的具体实现,我们只需要关注第一步创建bean实例即可,第一步是根据中的元数据定义来决定使用哪种实例化方法BeanDefinition.主要有3种类型:instantiateUsingFactoryMethod工厂方法实例化的具体实现autowireConstructor带参数构造函数实例化的具体实现Constructor)"实例化策略(cglib或反射)"?工厂方法i的实例化方法s是直接通过反射实现的,没有选择策略,所以这个实例化策略是针对构造函数的实例化?下面选择一个instantiateBean无论使用上面提到的两种构造函数实例化方式中的哪一种,都会选择一种实例化策略,使用哪一种选择的策略也是根据BeanDefinition中的定义来决定的。下面这行代码是选择实例化策略的代码beanInstance=getInstantiationStrategy().instantiate(mbd,beanName,parent);“选择使用反射还是cglib”首先判断beanDefinition.getMethodOverrides()是否为空,即用户没有使用replace或者查找配置方式,直接使用反射简单快捷。但是如果使用这两个特性,直接使用反射创建实例是不合适的,因为这两个配置提供的功能需要切入,所以需要使用动态代理的方式来设置拦截enhancer,包含两个特性对应的逻辑,这样可以保证方法调用时,会被对应的拦截器增强,返回值是包含拦截器的代理实例-----Spring源码深度解析>如果使用查找或者替换配置,则使用cglib,否则直接使用反射。publicstaticfinalStringLOOKUP_METHOD_ELEMENT="lookup-method";publicstaticfinalStringREPLACED_METHOD_ELEMENT="replaced-method";觉得不错,点个赞就走,谢谢参考:深入解析Spring源码SpringInActionhttps://url.ms/owy8p本文转载自微信公众号“月亮与飞鱼”,可通过以下二维码关注。转载本文请联系月版飞语公众号。