《Spring揭秘》--IOC笔记

容器的使用

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.

原文地址:https://www.cnblogs.com/cheungchein/p/8944251.html