通常,我们称 BeanFactory 为SpringIOC的基础容器 ApplicationContext 是容器的⾼级接⼝,⽐ BeanFactory 要拥有更多的功能,比如说国际化支持和资源访问(xml,java配置类)等等
Java环境下启动IOC容器
在spring框架管理Bean对象的创建时,Bean对象默认都是单例的,但是它⽀持配置的⽅式改变作⽤范围。作⽤范围官⽅提供的说明如下图:
在上图中提供的这些选项中,我们实际开发中⽤到最多的作⽤范围就是singleton(单例模式)和prototype(原型模式,也叫多例模式)。配置⽅式参考下⾯的代码:
<!--配置service对象--> <bean id="transferService" class="com.lagou.service.impl.TransferServiceImpl" scope="singleton"> </bean>
⼀句话总结:单例模式的bean对象⽣命周期与容器相同
⼀句话总结:多例模式的bean对象,spring框架只负责创建,不负责销毁
在基于xml的IoC配置中,bean标签是最基础的标签。它表示了IoC容器中的⼀个对象。换句话说,如果⼀个对象想让spring管理,在XML的配置中都需要使⽤此标签配置,Bean标签的属性如下:
依赖注⼊分类
按照注⼊的⽅式分类
按照注⼊的数据类型分类
哪些bean的定义写在xml中,哪些bean的定义使⽤注解
第三⽅jar中的bean定义在xml,⽐如德鲁伊数据库连接池,⾃⼰开发的bean定义使⽤注解
xml形式 | 对应的注解形式 |
---|---|
标签 | @Component("accountDao"),注解加在类上bean的id属性内容直接配置在注解后⾯如果不配置,默认定义个这个bean的id为类的类名⾸字⺟⼩写;另外,针对分层代码开发提供了@Componenet的三种别名@Controller、@Service、@Repository分别⽤于控制层类、服务层类、dao层类的bean定义,这四个注解的⽤法完全⼀样,只是为了更清晰的区分⽽已 |
标签的scope属性 | @Scope("prototype"),默认单例,注解加在类上 |
标签的init- method属性 | @PostConstruct,注解加在⽅法上,该⽅法就是初始化后调⽤的⽅法 |
标签的destory- method属性 | @PreDestory,注解加在⽅法上,该⽅法就是销毁前调⽤的⽅法 |
Bean的延迟加载(延迟创建)
ApplicationContext容器的默认⾏为是在启动服务器时将所有 singletonbean提前进⾏实例化。提前实例化意味着作为初始化过程的⼀部分,ApplicationContext 实例会创建并配置所有的singleton bean
⽐如:
lazy-init="false",⽴即加载,表示在spring启动时,⽴刻进⾏实例化。
如果不想让⼀个singleton bean 在 ApplicationContext实现初始化时被提前实例化,那么可以将bean
设置为延迟实例化。
设置 lazy-init为 true的 bean将不会在 ApplicationContext启动时提前被实例化,⽽是第⼀次向容器通过 getBean索取 bean时实例化的。
如果⼀个设置了⽴即加载的 bean1,引⽤了⼀个延迟加载的 bean2 ,那么 bean1 在容器启动时被实例化,⽽ bean2 由于被 bean1 引⽤,所以也被实例化,这种情况也符合延时加载的 bean 在第⼀次调⽤时才被实例化的规则。
也可以在容器层次中通过在 元素上使⽤ "default-lazy-init" 属性来控制延时初始化。如下⾯配置:
如果⼀个 bean 的 scope 属性为 scope="pototype" 时,即使设置了 lazy-init="false",容器启动时也不会实例化bean,⽽是调⽤ getBean ⽅法实例化的。
(1)开启延迟加载⼀定程度提⾼容器启动和运转性能
(2)对于不常使⽤的 Bean设置延迟加载,这样偶尔使⽤的时候再加载,不必要从⼀开始该 Bean就占
⽤资源
BeanFactory接⼝是容器的顶级接⼝,定义了容器的⼀些基础⾏为,负责⽣产和管理Bean的⼀个⼯⼚, 具体使⽤它下⾯的⼦接⼝类型,⽐如ApplicationContext;此处我们重点分析FactoryBean
Spring中Bean有两种,⼀种是普通Bean,⼀种是⼯⼚Bean(FactoryBean),FactoryBean可以⽣成某⼀个类型的Bean实例(返回给我们),也就是说我们可以借助于它⾃定义Bean的创建过程。
Bean创建的三种⽅式中的静态⽅法和实例化⽅法和FactoryBean作⽤类似,FactoryBean使⽤较多,尤 其在Spring框架⼀些组件中会使⽤,还有其他框架和Spring框架整合时使⽤
Company类
CompanyFactoryBean类
xml配置
测试,获取FactoryBean产⽣的对象
测试,获取FactoryBean,需要在id之前添加“&”
Spring提供了两种后处理bean的扩展接⼝,分别为 BeanPostProcessor 和
BeanFactoryPostProcessor,两者在使⽤上是有所区别的。
⼯⼚初始化(BeanFactory)—> Bean对象
在BeanFactory初始化之后可以使⽤BeanFactoryPostProcessor进⾏后置处理做⼀些事情
在Bean对象实例化(并不是Bean的整个⽣命周期完成)之后可以使⽤BeanPostProcessor进⾏后置处 理做⼀些事情
注意:对象不⼀定是springbean,⽽springbean⼀定是个对象
SpringBean的⽣命周期
2.3.1 BeanPostProcessor
BeanPostProcessor是针对Bean级别的处理,可以针对某个具体的Bean.
该接⼝提供了两个⽅法,分别在Bean的初始化⽅法前和初始化⽅法后执⾏,具体这个初始化⽅法指的是 什么⽅法,类似我们在定义bean时,定义了init-method所指定的⽅法
定义⼀个类实现了BeanPostProcessor,默认是会对整个Spring容器中所有的bean进⾏处理。如果要对 具体的某个bean处理,可以通过⽅法参数判断,两个类型参数分别为Object和String,第⼀个参数是每个bean的实例,第⼆个参数是每个bean的name或者id属性的值。所以我们可以通过第⼆个参数,来判断我们将要处理的具体的bean。
注意:处理是发⽣在Spring容器的实例化和依赖注⼊之后。
BeanFactory级别的处理,是针对整个Bean的⼯⼚进⾏处理,典型应
⽤:PropertyPlaceholderConfigurer
此接⼝只提供了⼀个⽅法,⽅法参数为ConfigurableListableBeanFactory,该参数类型定义了⼀些⽅法
其中有个⽅法名为getBeanDefinition的⽅法,我们可以根据此⽅法,找到我们定义bean 的
BeanDefinition对象。然后我们可以对定义的属性进⾏修改,以下是BeanDefinition中的⽅法
⽅法名字类似我们bean标签的属性,setBeanClassName对应bean标签中的class属性,所以当我们拿 到BeanDefinition对象时,我们可以⼿动修改bean标签中所定义的属性值。
B e an D e fi nition 对象: 我们在XML中定义的bean标签,Spring解析bean标签成为⼀个JavaBean,这个JavaBean就是BeanDefinition
注意:调⽤ BeanFactoryPostProcessor ⽅法时,这时候bean还没有实例化,此时 bean 刚被解析成
BeanDefinition对象