容器的使用
autowire
<bean>的属性,指定当前bean定义采用某种类型的自动绑定模式.共有5种,
no 默认
byName 类中声明的实例变量的名称,与XML配置文件中声明的bean定义的beanName的值进行匹配.
byType 如果找到一个,则绑定到相应的bean定义中,如果找不到不做设置,如果找到多个,则无法选用哪一个,需手动配置.
constructor 针对构造方法参数的类型而进行的绑定,其他与byType类似
autodetect byType和constructor的结合,如果对象拥有无参构造函数,则考虑byType模式,否则使用constructor模式
BeanFactory与ApplicationContext
bean的scope
singleton
prototype
request
session
global-session
工厂方法与FactoryBean
静态工厂方法
<bean class= factory-method= >
<constructor-arg>
</constructor-arg>
</bean>
非静态工厂
<bean factory-bean= factory-method= >
FactoryBean
Spring容器提供的一种可以扩容容器对象实例化逻辑的接口,只是一个Bean,是一个生产对象的工厂.
Prototype的陷阱
prototype类型的Bean并不能完全保证每次调用都让容器返回新的对象实例,以下方法则可以达到此目的.
方法注入
声明如下 public|protected [abstract] <return-type> theMethodName (no-arguements)
相应bean配置如下: <lookup-method name=theMethodName bean = ... />
原理:方法需要被子类实现或重载,因为容器会为我们要注入的对象使用Cglib动态生成一个子类实现,从而替换当前对象.
BeanFactoryAware接口
继承该接口,直接使用BeanFactory.getBean获取新的Bean
ObjectFactoryCreatingFactoryBean
这是Spring提供的一个FactoryBean的实现,返回的是一个FactoryBean的实例.也实现了BeanFactoryAware接口,隔离了客户端对象对于BeanFactory的直接引用.
类似的,也可以使用ServiceLocatorFactoryBean.
方法替换
给出org.springframework.beans.factory.support.MethodReplacer的实现,在相应的Bean中配置如下:
<replaced-method name=... replacer= ...> </replaced-method>
注意:该方法的效率不是很高.
容器的真相
容器的启动
准备性的工作,侧重于对象管理信息的手机,也包括一些验证性或辅助性的工作.
Bean的实例化
当某个请求方通过容器的getBean方法明确地或隐式的请求某个对象时,就会启动该阶段.
BeanFactoryPostProcessor容器扩展机制
作用:在容器实例化相应对象之前,对注册到容器的BeanDefinition所保存的信息作相应的修改.
配置:BeanFactory中需要用手动方式应用所有的BeanFactoryPostProcessor. ApplicationContext中会自动识别配置文件中的BeanFactoryPostProcessor并应用它.
PropertyPlaceholderConfigurer
在xml配置文件中使用占位符,并将这些占位符所代表的资源单独配置到简单的properties文件中加载. 例如${property}.
PropertyPlaceholderConfigurer还会检查java的System类中的Properties,可以通过setSystemPropertiesMode()或者setSystemPropertiesModeName()来控制是否加载或者覆盖System相应Properties的行为.
PropertyPlaceholderConfigurer有三种模式,SYSTEM_PROPERTIES_MODE_FALLBACK(默认), SYSTEM_PROPERTIES_MODE_NEVER, SYSTEM_PROPERTIES_MODE_OVERRIDE.默认即在propoerties文件中找不到相应的配置项.
PropertyOverrideConfigurer
对容器中配置的任何你想处理的bean定以的properties信息进行覆盖替换.
配置项格式为: beanName.propertyName=value
以上两个都是通过对BeanDefinition中的数据进行变更以达到某种目的.
CustomEditorConfigurer
他只是辅助性地将后期会用到的信息注册到容器,对BeanDefinition没有做任何变动.
Spring会默认地加载几种PropertyEditor.如果我们需要执行的类型没有包含在以上所提到的PropertyEditor之列的时候,就需要给出针对这种类型的PropertyEditor实现,并通过配置CustomEditorConfigurer告知容器.
在2.0之后,比较提倡使用propertyEditorRegistrars属性来制定自定义的PropertyEditor.不过需要多给出一个PropertyEditorRegistrar的实现.
Bean的一生
BeanFactory中对象实例化默认采用延迟初始化. ApplicationContext启动之后会实例化所有的bean定义.在启动阶段的活动完成之后,紧接着调用注册到该容器的所有bea定义的实例化方法getBean().
1. Bean的实例化与BeanWrapper
容器在内部实现的时候,采用策略模式来决定以何种方式初始化bean实例.
org.springframework.beans.factory.support.InstantiationStrategy定义是实例化策略的抽象接口,以反射方法实例对象.
直接子类SimpleInstantiationStrategy通过反射来实例化对象实例;CglibSubclassingInstantiationStrategy继承了SimpleInstantiationStrategy以反射实例化对象的功能,并且通过CGLIB的动态字节码生成功能,动态生成某个类的子类,进而满足了方法注入所需的对象实例化需求,这是容器的默认生成方法.
返回实例化完成的对象实例是以BeanWrapper对构造完成的对象实例进行包裹,返回相应的BeanWrapper实例. 以上是第一步.
第二步是设置对象属性.将各种PropertyEditor注册给容器时,BeanWrapper在之后将使用这些PropertyEditor.
2.各色的Aware接口
在对象实例化完成并且相关属性以及依赖设置完成之后,Spring容器会将当前对象是否有实例一系列Aware命名的接口定义,并按定义中的规定来注入给当前对象实例.
相关Aware接口涉及的有BeanNameAware, BeanClassLoaderAware, BeanFactoryAware(BeanFactory容器将自身设置到当前对象实例,可以对这个容器内允许访问的对象按需访问).
而对于ApplicationContext类型的容器,也存在介个Aware相关接口,但使用的是BeanPostProcessor方式.这些接口有ResourceLoaderAware, ApplicationEventPublishAware, MessageAware, ApplicationContextAware.
3.BeanPostProcessor
BeanPostProcessor支持前置处理及后置处理,我们几乎可以对传入的对象实例执行任何的操作.
比较常见的使用场景是处理标机接口实现类,为当前对象提供代理实现.其他的有替换当前对象实例或者字节码增强当前对象实例.
Spring的AOP则更多地用它来为对象生成代理对象.
4. InitializingBean和init-method
若当前对象实现了InitializingBean接口,在实例化之后,会调用该接口的afterPropertiesSet()方法进一步调整对象实例的状态.这种方法比较有侵入性.
另一种指定自定义的对象初始化操作是在XML配置bean中使用init-Method属性.还可以在<beans>中的default-init-method统一制定这一init()的方法名.
5.DisposableBean与destroy-method
在设置,注入,调用完成之后,容器江湖检查singleton类行的bean实例,看其是否实现了DisposableBean接口,或是器bean定义是否通过destroy-method指定了自定义的对象销毁方法.如果是,则为该实例注册一个用于对象销毁的接口回调Destruction,以便这些对象在销毁之前,执行销毁逻辑.常见的场景比如数据库连接池.
在Spring容器关闭之前,不会自动调用这些回调方法,需要告知容器,在哪个时间点来执行对象的之定义销毁方法.
对于BeanFactory容器来说,需要在独立应用程序的主程序退出之前,或是其他合适的情况下,调用ConfigurableBeanFactory提供的destroySingleton()方法销毁容器中的所有Singleton类型的对象实例.
对于ApplicationContext容器来说,道理是一样的,但是AbstractApplicationContext提供了registerShutdownHook()方法,该方法底层使用Runtime类的addShutdownHook()的方式调用相应bean对象的销毁逻辑(其中还包括ApplicationContext相关的时间发布).
另外,prototype类型的bean实例,对象在容器实例化并返回给请求方之后,容器就不在管理这种类型对象实例的生命周期了.
ApplicationContext
统一资源加载策略
Resource 实现类: ByteArrayResource ClassPathResource URLResource InputStreamResource
ResourceLoader 实现类:DefaultResourceLoader FileSystemResourceLoader
ResourcePatternResolver(批量查找的ResourceLoader) 实现类:PathMatchingResourcePatternResolver(可以传入一个ResourceLoader或者使用默认的DefaultResourceLoader来加载资源,这样和ResourceLoader的区别就是返回Resource的数量多少)
用处: 扮演ResourceLoader的角色;ResourceLoader类型的注入;Resource的注入;特定情况下,ApplicationCOntext的Resource加载行为(ClassPathXMLApplicationContext与FileSystemXMLApplicationContext的某些相通性)
国际化信息支持
容器内事件发布
多配置模块加载的简化
基于注解的依赖注入
@Autowire 依据类型注入,可以应用于属性,构造方法,普通方法上. 使用时,还需要提供一个当前的IOC容器BeanPostProcessor的实现,即AutowiredAnnotationBeanPostProcessor
@Qualifier byName自动绑定的注解版; 还可以用来标注注解类型
JSR50注解
@Resource byName自动绑定,可以存在于属性或构造方法或普通方法
@PostConstruct 与 InitializingBean接口或配置项init-method功能类似
@PreDestroy 与DisposableBean接口或配置项中的destroy-method功能类似 以上使用时,还需要提供一个当前的IOC容器BeanPostProcessor的实现,即CommonAnnotationBeanPostProcessor
在配置文件中添加<context:annotation-config>可以搞定以上所有的BeanPostProcessor,同时还会把PersistenceAnnotationBeanPostProcessor及RequireAnnotationBeanPostProcessor一并进行注入.
<context:component-scan>可以触发classpath-scanning功能,从某一顶层包开始扫描,扫描到某个类标注了相应的注解(默认为@Component,以及基于其的@Repository,@Controller,@Service),就会提取该类信息,构建BeanDefinition,注册容器.
按默认规则为Bean命名,也可以通过@Component指定名字.
默认会将AutowiredAnnotationBeanPostProcessor及CommonAnnotationBeanPostProcessor注册到容器中,可以通过将属性annotation-config设为false关闭.
还可以通过设置<context:include-filter>丰富注解的范围,或者用<context:exclude-filter>排除一些注解. 这两个属性值的type类型有annotation,assignable,regex,aspectj.