文章目录
目录
前言
主要介绍了Beanfactory的功能和获取依赖和描述依赖的方式。
一、功能
- Ioc Service Provider对象创建+依赖注入,AOP支持,对象生命周期管理,线程管理
- 基础的Ioc容器,采用延迟初始化策略,实际访问对象时再创建并依赖注入
- Spring用XmlBeanFactory实现BeanFactory,XmlBeanFactory可以帮我们利用BeanDefinitionReader去解析配置文件,只需要传入ClassPathSource即可
二、获取依赖
- 获得依赖关系并注入的过程
- 直接编码方式
- 只需要DefaultListableBeanFactory当做BeanDefinitionRegistry来完成对象创建和依赖注入(手动将受管对象基本信息放入BeanDefinition实现类中,手动获得构造函数或者setter方法里的传入的依赖对象实例并注入,然后注册到BeanDefinitionRegistry),然后将这个DefaultListableBeanFactory转成BeanFactory,通过这个BeanFactory可以getbean
- 外部文件配置(XML文件 / properties文件)
- 代码逻辑基本一致(需要DefaultListableBeanFactory当做BeanDefinitionRegistry,作为bind函数的参数传入,用于接收受控对象的BeanDefinition)
- BeanDefinitionReader实现类根据loadBeanDefinitions函数中传入的扫描路径,找到XML文件并解析,获得Ioc容器里的被控对象,并解析对象间的依赖关系,将被控对象信息放入BeanDefinition,然后BeanDefinition可以注册到BeanDefinitionRegistry中,完成Bean的注册和加载
- 基于注解
- 标注了注解@component 的类会被放入容器中统一管理
- 标注了注解@Autowired 的属性会进行依赖注入
- 直接编码方式
- 获得依赖关系并注入的过程的各种名词解释
- DefaultListableBeanFactory
- 通用的BeanFactory实现类
- 实现BeanFactory和BeanDefinitionRegistry两个接口
- BeanFactory
- 充当Bean注册过程的管理角色
- BeanDefinitionRegistry
- 完成实际的Bean注册和依赖注入工作
- BeanDefinition
- 每个受管的对象有一个BeanDefinition实现类(RootBeanDefinition和ChildBeanDefinition)的实例用于存取对象的必要信息
- 客户端向BeanFactory请求对象时,通过BeanDefinition中的信息返回一个完备可用的对象实例
- BeanDefinitionReader
- BeanDefinitionReader实现类可以读取配置文件内容并将其中的管理对象信息放入BeanDefinition,然后BeanDefinition可以注册到作为参数传入的BeanDefinitionRegistry中,完成Bean的注册和加载
- loadBeanDefinitions函数传入配置文件的路径,然后会自动实现受控对象信息放入BeanDefinition的过程
- XMLBeanFactory
- DefaultListableBeanFactory的基础上构建的简化XML配置加载,一行代码(只需要将配置文件地址作为参数传入)实现BeanDefinitionReader的过程
- DefaultListableBeanFactory
三、描述依赖
- XML配置文件中的bean---通过配置文件写明白bean对象之间的依赖关系
- bean的横向依赖关系
(普通数据类型/实例对象)- 手动依赖注入
- 构造方法注入怎么写XML
- <constructor-arg >
- setter方法注入怎么写XML
- <property>
- 可以配置在constructor或者property里面的
- 依赖的是普通数据类型
- value="xxx"
- 注入一个具体值
- list、set
- 一个有序,一个无序
- map、props
- k-v类型,props的k只能是string
- <null/>
- value="xxx"
- 依赖的是对象
- ref
- ref=“xxx” 注入依赖对象的引用
- ref local/parent/bean=“xxx” 注入的依赖对象引用有范围限定
- idref bean=“xxx” 注入依赖对象的名字
- bean
- 内部bean,只能被当前所在的bean对象访问,其他与普通bean无区别
- ref
- 依赖的是普通数据类型
- depands-on非显示依赖关系
- 构造方法注入怎么写XML
- autowire自动绑定/依赖注入
- bytype
- 容器里只有一个依赖类型的bean可以自动注册,否则只能手动配置
- byname
- 根据依赖对象的name找到容器里id与之相同的bean,完成自动注册
- property可以设置byname和bytype两种autowire
- constructor是bytype类型的autowire,根据传入构造方法参数的类型
- bytype
- dependency-check 依赖检查一般与autowire一起用
- none不检查,simple检查简单数据类型依赖是否注入成功,object检查依赖对象是否注入成功,all所有依赖注入是否成功
- lazy-init
- beanFactory默认延迟初始化,ApplicationContext默认启动就完成初始化,可以通过lazy-init使其延迟初始化
- 手动依赖注入
- bean的纵向继承关系
- bean可以设置parent属性
- bean可以设置abstract属性,abstract属性为true就无需配置class属性,初始化阶段不会实例化
- 一群默认配置相同的bean可以继承一个abstract属性为true的bean,在该abstract bean里写一份默认配置,继承的bean可以继承这些默认配置
- Aplicationcontext里不想初始就实例化的bean,可以设置其abstract属性为true
- bean的scope(作用域)
- singleton(单例bean)
- scope是singleton的对象在Ioc容器里面只有一个实例,在第一次请求时会被初始化,所有该对象的引用共享一个实例,该实例会一直存活到容器退出,和Ioc容器几乎有着相同时间的寿命
- 单例bean模式保证同一个Ioc容器里只保持一个bean实例对象,所有bean依赖共享这个实例,可以有好多个bean但是这些bean都依赖一个实例
- 单例模式(保证在一个classloader中只存在一个这种类型的实例,一个类只有一个对象),实现方式
- 饿汉式
- 类装载时就完成实例化--没有lazy init
- 对象设为静态常量
- 静态代码块里创建实例)
- 类装载时就完成实例化--没有lazy init
- 懒汉式
- 线程不安全
- 单线程时判断没有对象则创建
- 同步代码块里判断没有对象就创建
- 线程安全
- 同步加锁只允许一个线程创建,效率低
- 双重检查,先检查一次对象为空,再上锁并检查一次对象为空才创建
- 线程不安全
- 静态内部类
- 和饿汉一样,装载阶段实例化,
- 但是只有实例化时才装载实例对象,实现了lazy-init
- 枚举
- 避免多线程同步的同时,防止反序列化创建新对象
- 饿汉式
- prototype(原型/多例bean)
- 每一次请求都由Ioc容器创建一个新的实例对象,然后交给请求方,Ioc容器不再持有这个实例的引用,该实例对象存活周期由请求方自行管理
- 只能在web应用中使用的scope,只在XmlWebApplicationContext中使用
- request
- 每一个请求创建一个新的请求对象RequestProcessor对象实例,类似prototype,请求结束,该对象生命周期就结束了
- session
- 每个用户登录信息会放到session中,每一个session会创建一个新的UserPreferences对象实例,比request scope活的久一点
- global session
- 只在portlet的web应用程序中有意义,还是一个UserPreferences实例对象,和session差不多
- request
- 自定义scope
- 自定义scope通过实现scope接口,并且实现其get和remove方法,注册该scope后可以供bean使用
- scope的注册方式
- 直接编码注册scope
- 直接编码通过ConfigurableBeanFactory的registerScope注册自定义的scope供bean使用
- 写在xml配置文件,bean工厂统一注册
- BeanFactoryPostProcessor可以实现自定义scope的统一注册
- ApplicationContext可以自动识别BeanFactoryPostProcessor
- 可以直接在配置文件里通过class类型为CustomScopeConfigurer的bean来统一注册所有自定义scope
- 直接编码注册scope
- singleton(单例bean)
- bean依赖接口--工厂方法/FactoryBean
依赖工厂方法,由他完成接口实现类的创建- 如果bean依赖接口,必须将bean与接口实现类相关联
- 自己开发只需要,自定义写接口实现类,并在bean里依赖注入接口实现类
- 依赖第三方接口,不适合自己写接口实现类,通过工厂方法实现接口实现类,依赖工厂方法获取它创造出来的接口实现类
- 静态工厂方法
- <bean id="xx" class="...StaticxxInterfaceFactory" factory-method="getInstance"/>
从class指定的静态工厂里面,通过factory-method对应的方法,取出接口实现类,作为id为xx的bean注入 - <constructor -arg> <ref bean="xxx"> </constructor -arg>
若构造实例的方法需要传入参数,通过constructor为工厂方法里的构造实例函数传入xxx依赖(不是传入工厂的构造函数)
- <bean id="xx" class="...StaticxxInterfaceFactory" factory-method="getInstance"/>
- 非静态工厂方法
- <bean id="xx" class="...StaticxxInterfaceFactory"/>
将工厂作为一个普通bean依赖注入 - <bean id="xx" factory-bean="xxFactory" factory-method="getInstance"/>
factory-bean指明一个工厂实例,在工厂实例里面通过factory-method获得接口实现类,作为id=xx的bean注入 - <constructor -arg> <ref bean="xxx"> </constructor -arg>
构造实例方法参数的传入
- <bean id="xx" class="...StaticxxInterfaceFactory"/>
- FactoryBean
- FactoryBean本身是一个被注入Ioc容器(BeanFactory)的一个有点特殊的bean,用来创造容器中依赖接口的bean所依赖的接口实现类
- XML文件配置将自定义的工厂方法注入写起来很麻烦(先注入工厂,再通过工厂实例找到方法,方法里面创建实例对象),直接实现FactoryBean接口,在FactoryBean实现类里面写对象实例化逻辑代码,然后将这个FactoryBean实现类作为一个普通的bean注入Ioc容器(beanFactory),可以由它来完成接口实现类创建
- 将FactoryBean注入容器以后,依赖接口的bean和依赖普通对象的bean写法没有任何区别,直接通过id在factorybean里面拿到接口实现类实例
如果是自定义工厂方法,需要在bean里面先注入工厂方法依赖,然后先拿到通过工厂方法实现类,在里面找到生成实例对象的方法,然后拿到这个方法创建的接口实现类实例,无法直接拿到接口实现类对象 - 直接通过getBean(id)拿到的是接口实现类对象,想拿工厂FactoryBean可以通过&符号,getBean(&id)
- 如果bean依赖接口,必须将bean与接口实现类相关联
- bean的方法替换
- 方法里创建一个新的依赖对象替换旧的对象
- 场景
- 一个类中有一个变量是一个对象,同时有一个方法可以获得该对象,想要实现每次通过方法获得对象时拿到的都是新创建的对象
将被依赖的对象scope设置为prototype无法实现,只有第一次getbean实例化类对象的时候,容器会帮我们依赖注入一次这个被依赖的对象,而后这个类一直持有第一次创建的该对象,每次调用方法获得这个对象时,拿到的都是同一个
- 一个类中有一个变量是一个对象,同时有一个方法可以获得该对象,想要实现每次通过方法获得对象时拿到的都是新创建的对象
- 方法注入<lookup-method>
- <lookup-method name="xxx" bean="aaa"/>
在配置类时,通过lookup-method实现在每次调用xxx方法时,通过Cglib动态生成一个子类aaa替代当前对象
- <lookup-method name="xxx" bean="aaa"/>
- BeanFactoryAware接口
- 满足每次调用方法时都去getbean获得新的依赖对象(prototype类型保证每次getbean创建新的对象),也可以实现上述功能
- 让类实现BeanFactoryAware接口,这样容器拿到该类的bean定义后,会将容器本身注入到这个类,类可以通过拥有一个私有beanfactory成员,然后在调用方法时通过beanfactory去调用getbean方法,保证每次拿到新的依赖对象
- 注入ObjectFactoryCreatingFactoryBean
- 是FactoryBean的一个实现,返回一个ObjectFactory实例,它可以为我们创建容器管理的相关对象,避免了客户端对象对beanfactory的直接引用
- ObjectFactoryCreatingFactoryBean实现了BeanFactoryAware接口,返回的ObjectFactory是有限制条件的beanfactory,只可以通过她创造容器中的某个特定被控对象实例,不能用容器做其他事
- 只需要在类里面定义一个ObjectFactory的成员,在配置文件里面注入ObjectFactoryCreatingFactoryBean,并指明其创建的objectfactory可以创建的被控对象类型即可
- 场景
- 创建新的方法逻辑覆盖旧的方法逻辑
- 方法替换<replaced-method>
- 写一个MethodReplacer实现类,在里面写需要替换的方法逻辑,注入到容器里,创建其实例对象xx
- 在配置文件里,在需要替换方法的类的bean定义中通过<replaced-method name=“aa” replacer=“xx”>将aa方法替换为xx
- 方法替换<replaced-method>
- 方法里创建一个新的依赖对象替换旧的对象
- bean的横向依赖关系