Spring容器初始化,Bean生命周期

Spring是什么?由来,思想,特性?

Spring是一套为了解决企业应用开发的复杂性而创建的框架,特点是分层的架构,允许用户在不同层面使用不同的组件进行组合。同时通过IOC容器来降低耦合,简化开发。利用AOP来进行切面编程统一管理通用模块。

Sping由哪些产品组成?作用,特点,使用场景?

我在工作中用到过Spring的IOC容器和AOP面向切面编程。

在项目中使用IOC容器帮我很好的理清各个业务对象的关系,同时方便不同组件的更替。

在做接口权限验证时,使用AOP切面编程帮助我能很快的对需要进行验证的接口完成验证功能的实现。并且统一进行管理,提高开发效率。 

Spring Bean的生命周期?

这里bean的生命周期是下面IOC容器初始化中的第二步。如何去创建一个bean

Spring 只帮我们管理单例模式 Bean 的完整生命周期,对于 prototype 的 bean ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。

ApplicationContext factory = new ClassPathXmlApplicationContext("springBeanTest/beans.xml");通过xml文件来初始化IOC容器,在初始化的过程中,我们创建了一个个的Bean

 

第一步三个阶段主要是IOC容器自身的一些构造器的实例化。

包括实例化BeanFactoryPostProcessor实现类->实例化BeanPostProcessor实现类(增强处理器)->实例化InstantiationAwareBeanPostProcessorAdapter实现类

 

第二步postProcessBeforeInstantiation方法->Bean的构造方法->postProcessPropertyValues()方法(均来自上面的第三个类里面的方法)->为Bean注入属性(包括Bean的id属性BeanNameAware接口的setBeanName方法,Bean的beanfactory实例引用BeanFactoryAware的setBeanFactory方法)

 注入属性以后如果Bean实现了InitializingBean接口会调用它里面的afterPropertiesSet()方法。

第三步增强处理器(BeanPostProcessor)发挥作用 postProcessBeforeInitialization->bean init-method自定义的初始化方法->postProcessAfterInitialization->最后调用InstantiationAwareBeanPostProcessorAdapter的postProcessAfterInstantiation方法完成初始化

 

销毁过程:

首先调用DisposableBean 接口的 destroy() 方法。然后调用<bean>标签中 destroy-method自定义的销毁方法。

 

上面的这种主要通过BeanPostProcessor这个接口来实现Bean的生命周期

 

我们也可以通过@PostConstruct(对象创建以后调用)和@PreDestroy(对象被移除 之前调用)这两个注解,这两个注解都是加到方法上面的。

 

Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

1、Bean自身的方法  :  这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法

2、Bean级生命周期接口方法  :  这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法

3、容器级生命周期接口方法  :  这个包括了InstantiationAwareBeanPostProcessor(适配器类InstantiationAwareBeanPostProcessorAdapter ) 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。

4、工厂后处理器接口方法  :  这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

 

参考:

https://www.cnblogs.com/zrtqsk/p/3735273.html(写的非常好)

Bean的作用域有哪些?

singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例,ioc容器中默认就是单例模式,在创建ioc容器的时候,就会默认初始化所有的单例bean,而且这个作用域下的所有bean的整个生命周期都是由ioc容器来管理,由他来创建,由它来销毁。

prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例,ioc容器只负责对他的创建,至于销毁是由客户端来帮忙实现。

request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效,与prototype所不同的是,这个创建以后,spring仍然在监听

session:对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效

globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。

引申:controller是单例还是多例?

配置默认是单例(singleton),不能非静态属性。如果里面有其他的实例变量就会出现线程安全问题。‘

解决方法:

有几种解决方法:
1、在Controller中使用ThreadLocal变量
2、在spring配置文件Controller中声明 scope="prototype",每次都创建新的controller
所在在使用spring开发web 时要注意,默认Controller、Dao、Service都是单例的。

 

Spring中的核心类?

BeanFactory:产生一个新的实例,可以实现单例模式
BeanWrapper:提供统一的get及set方法
ApplicationContext:提供框架的实现,包括BeanFactory的所有功能

 

BeanFactory和FactoryBean区别:

BeanFactory是IOC最基本的容器,负责生产和管理bean,接口里面主要有getBean(),isSingleton(),isPrototype()等方法

FactoryBean:

public interface FactoryBean<T> {  
    T getObject() throws Exception;  
    Class<?> getObjectType();  
    boolean isSingleton();  
}

FactoryBean是一个接口,当在IOC容器中的Bean实现了FactoryBean后,通过getBean(String BeanName)获取到的Bean对象并不是FactoryBean的实现类对象,而是这个实现类中的getObject()方法返回的对象。要想获取FactoryBean的实现类,就要getBean(&BeanName),在BeanName之前加上&
FactoryBean在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式,我们可以在getObject()方法中灵活配置。(相当于通过getObject这个方法作为一个简单工厂)

关于BeanFactory和Application两者的区别:

BeanFactory:是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能;

ApplicationContext:

应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能;用的最多的包括AOP(拦截器),访问资源,如URL和文件(ResourceLoader)

装载的区别:

BeanFactory:

BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化;

ApplicationContext:

ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化;

我们该用BeanFactory还是ApplicationContent

 

延迟实例化的优点:(BeanFactory)

应用启动的时候占用资源很少;对资源要求较高的应用,比较有优势; 

 

不延迟实例化的优点: (ApplicationContext)

1. 所有的Bean在启动的时候都加载,系统运行的速度快; 

2. 在启动的时候所有的Bean都加载了,我们就能在系统启动的时候,尽早的发现系统中的配置问题 

3. 建议web应用,在启动的时候就把所有的Bean都加载了。(把费时的操作放到系统启动中完成)

 

 

在springBoot如何获得一个bean实例:

1.通过autowired注解的方式注入

2.获得ApplicationContext对象:

注入获取,

通过xml文件获取

ApplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml"),

ApplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml");

通过配置类获取,

JavaConfigApplicationContext ac= new JavaConfigApplicationContext(ApplicationConfig.class)

ac.getBean("beanId") 

 

Spring IOC容器初始化的过程?

 

1.Bean定义的定位,Bean 可能定义在XML中,或者一个注解,或者其他形式。这些都被用Resource来定位, 读取Resource获取BeanDefinition 注册到 Bean定义注册表中。

    这个过程包括:

    Resource定位(Bean的定义文件定位)

    有的通过xml文件加载资源XmlWebApplicationContext.getResource,有的通过注解的方式加载资源AnnotationConfigApplicationContext,返回Resource对象

    将Resource定位好的资源载入到BeanDefination

    整个过程通过loadBeanDefintions(Resource对象),与容器对应的XXXReader对象,就是通过这个对象载入所有的BeanDefination,BeanDefinition实际上就是POJO对象在IOC容器中的抽象,bean实际上就是在ioc容器内部表示成了BeanDefinition这样的数据结构,使IOC容器能够方便地对POJO对象也就是Bean进行管理。

   在加载Resource对象的时候有这个方法,去解析xml这些文件

   是parseBeanDefinitionElement(ele, null)方法中产生了一个抽象类型的BeanDefinition实例,这也是我们首次看到直接定义BeanDefinition的地方,这个方法里面会将<bean>标签中的内容解析到BeanDefinition中,之后再对BeanDefinition进行包装,将它与beanName,Alias等封装到BeanDefinitionHolder 对象

   将BeanDefination注册到容器中

   最终Bean配置会被解析成BeanDefinition并与beanName,Alias一同封装到BeanDefinitionHolder类中, 之后beanFactory.registerBeanDefinition(beanName, bdHolder.getBeanDefinition()),注册到DefaultListableBeanFactory.beanDefinitionMap(一个hashmap)中,oc容器就是通过这个hashmap来持有这些BeanDefination数据的。

   在之后我们就是通过beanname来获取bean的定义进而创建一个bean实例

 

2.第一次向容器getBean操作会触发Bean的创建过程,实列化一个Bean时 ,根据BeanDefinition中类信息等实列化Bean.

 

3.将实列化的Bean放到单列Bean缓存内。

 

4.此后再次获取向容器getBean就会从缓存中获取。

 

参考:

https://www.cnblogs.com/chenjunjie12321/p/6124649.html

posted @ 2019-03-11 15:51  LeeJuly  阅读(680)  评论(0编辑  收藏  举报