一般,咱们称BeanFactory为SpringIOC的基础容器ApplicationContext是容器的⾼级接⼝,⽐BeanFactory要拥有更多的功能,好比说国际化支持和资源访问(xml,java配置类)等等java
Java环境下启动IOC容器spring
在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标签的属性以下:app
依赖注⼊分类框架
按照注⼊的⽅式分类ide
按照注⼊的数据类型分类函数
注意:性能
哪些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
⽐如:
<bean id="testBean" class="cn.boc.LazyBean" /> 该bean默认的设置为: <bean id="testBean" class="cn.boc.LazyBean" lazy-init="false" />
lazy-init="false",⽴即加载,表示在spring启动时,⽴刻进⾏实例化,若是使用注解则为@Lazy,默认参数就是true
import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; @Component @Lazy public class BeanExp { }
若是不想让⼀个singleton bean 在 ApplicationContext实现初始化时被提早实例化,那么能够将bean设置为延迟实例化
<bean id="testBean" class="cn.boc.LazyBean" lazy-init="false" />
设置 lazy-init为true
的 bean将不会在 ApplicationContext启动时提早被实例化,⽽是第⼀次向容器经过 getBean索取 bean时实例化的
若是⼀个设置了⽴即加载的 bean1,引⽤了⼀个延迟加载的 bean2 ,那么 bean1 在容器启动时被实例化,⽽ bean2 因为被 bean1 引⽤,因此也被实例化,这种状况也符合延时加载的 bean 在第⼀次调⽤时才被实例化的规则
也能够在容器层次中经过在 元素上使⽤ "default-lazy-init" 属性来控制延时初始化。以下⾯配置:
<beans default-lazy-init="true"> <!-- no beans will be eagerly pre-instantiated... --> </beans>
若是⼀个 bean 的 scope 属性为 scope="pototype"
时,即便设置了 lazy-init="false"
,容器启动时也不会实例化bean,⽽是调⽤ getBean ⽅法实例化的
Bean建立的三种⽅式中的静态⽅法和实例化⽅法和FactoryBean做⽤相似,FactoryBean使⽤较多,尤为在Spring框架⼀些组件中会使⽤,还有其余框架和Spring框架整合时使⽤
public class BeanExp3 { String name; String address; int type; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public int getType() { return type; } public void setType(int type) { this.type = type; } @Override public String toString() { return "BeanExp3{" + "name='" + name + '\'' + ", address='" + address + '\'' + ", type=" + type + '}'; } }
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class MyFactoryBean implements FactoryBean<BeanExp3> { @Value("测试Bean,中环大厦,1") public String info; @Override public BeanExp3 getObject() throws Exception { System.out.println("info:" + info); BeanExp3 beanExp3 = new BeanExp3(); String[] array = info.split(","); beanExp3.setName(array[0]); beanExp3.setAddress(array[1]); beanExp3.setType(Integer.valueOf(array[2])); return beanExp3; } @Override public Class<?> getObjectType() { return BeanExp.class; } }
<bean id="BeanExp3" class="com.boc.MyFactoryBean"> <property name="companyInfo" value="测试Bean,中环大厦,1"/> </bean>
Object beanExp3 = appcationContext.getBean("myFactoryBean"); System.out.println(beanExp3);
须要在id以前添加“&”
Object beanExp3 = appcationContext.getBean("&myFactoryBean"); System.out.println(beanExp3);
Spring提供了两种后处理bean的扩展接⼝,分别为 BeanPostProcessor和BeanFactoryPostProcessor,二者在使⽤上是有所区别的
⼯⼚初始化(BeanFactory)—> Bean对象
在BeanFactory初始化以后可使⽤BeanFactoryPostProcessor进⾏后置处理作⼀些事情
在Bean对象实例化(并非Bean的整个⽣命周期完成)以后可使⽤BeanPostProcessor进⾏后置处理作⼀些事情
注意:对象不⼀定是springbean,⽽springbean⼀定是个对象
SpringBean的⽣命周期
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标签中所定义的属性值。
BeanDefinition对象:咱们在XML中定义的bean标签,Spring解析bean标签成为⼀个JavaBean,这个JavaBean就是BeanDefinition
注意:调⽤ BeanFactoryPostProcessor ⽅法时,这时候bean尚未实例化,此时 bean 刚被解析成BeanDefinition对象