spring IoC简介及容器设计原理

Ioc:反转控制,与开发者主动创建对象的流程相比,理解上会有点困难,但它可以减低对象之间的耦合;由spring Ioc容器根据配置文件或注解自动完成对象(Bean)的实例化与对象之间的依赖关系设置并且进行管理;

1.Ioc容器的设计主要基于BeanFactory和ApplicationContext两个接口,其中BeanFactory是最底层接口,ApplicationContext是其高级接口之一;所以很多情况下,我们会使用ApplicationContext的实现类作为Ioc容器;推荐使用基于注解的Ioc容器:AnnotationConfigApplicationContext,示例如下:将配置文件AppConfig传递给AnnotationConfigApplicationContext构造方法,这样就可以读取配置了;

@Configuration
public class AppConfig{......}

ApplicationContext ctx=new AnnotationConfigApplicationContext(AppConfig.class);
ctx.getBean(xxx.class)

构建Ioc容器:构建入口在AbstractApplicationContext类中的refresh()方法;

@Override
publicvoid refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// 为刷新准备新的context.
		prepareRefresh();
		// 刷新所有BeanFactory子容器,创建BeanFactory.
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
		// 添加spring本身需要的工具类.
		prepareBeanFactory(beanFactory);
		try {
			// 注册实现了BeanPostProcessor接口的bean.
			postProcessBeanFactory(beanFactory);
			// 初始化和执行BeanFactoryPostProcessor beans.
			invokeBeanFactoryPostProcessors(beanFactory);
			// 初始化和执行BeanPostProcessor beans.
			registerBeanPostProcessors(beanFactory);
			// 初始化MessageSource.
			initMessageSource();
			// 初始化Event Multicaster.
			initApplicationEventMulticaster();
			// 刷新由子类实现的方法.
			onRefresh();
			// 检查注册的事件.
			registerListeners();
			// 初始化non-lazy-init单例Bean.
			finishBeanFactoryInitialization(beanFactory);
			// 执行LiecycleProcessor.onRefresh()和ContextRefreshedEvent事件.
			finishRefresh();
		}catch (BeansException ex) {
			if (logger.isWarnEnabled()) {
				logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
			}
	
			// 销毁已创建的单例beans.
			destroyBeans();
			// 重置'active'标识.
			cancelRefresh(ex);
			// 返回异常给调用者.
			throw ex;
		}finally {
			// 重置
			resetCommonCaches();
		}
	}
}

(1)准备新的context,提供spring运行时环境;
(2)构建BeanFactory:如下为创建的时序图,前一个方法中会调用后一个方法,为依次递进的关系;
obtainFreshBeanFactory()—— refreshBeanFactory() —— createBeanFactory() —— loadBeanDefinitions(beanFactory) —— new XmlBeanDefinitionReader(beanFactory);
刷新子容器,BeanFactory存在就更新,不存在就新建,BeanFactory的原始对象是DefaultListableBeanactory,然后加载、解析Bean的定义即把用户定义的数据结构转化为Ioc容器中的特定数据结构,使用XmlBeanDefinitionReader解析,解析出来的Bean定义放入beanDefinitionNames、beanDefinitionMap和aliasMap保存;
(3)添加一些spring本身需要的工具类;
(4)扩展spring功能:
postProcessBeanFactory和invokeBeanFactoryPostProcessors允许对已构建的BeanFactory的配置做修改;
invokeBeanFactoryPostProcessors获取实现了BeanPostProcessor接口的子类,并执行它的postProcessBeanactory方法以修改BeanFactory;
registerBeanPostProcessors获取用户定义的实现了BeanPostProcessor接口的子类,并注册到BeanFactory对象中的beanPostProcessors变量中;
BeanPostProcessor中有两个方法:postProcessBeforeInitialization在Bean对象初始化前,postProcessAfterInitialization在Bean对象初始化后,用于用户自定义操作;
(5)初始化监听事件和对系统的其他监听者的注册;
(6)创建Bean实例对象并设置关系网:实例化过程中会涉及到一个重要的Bean:FactoryBean,工厂Bean,如果一个类继承FactoryBean,用户就可以自定义产生实例对象的方法,只需实现它的getObject()即可;而在spring内部,通过调用这个getObject()方法就可以获取到用户自定义产生的对象;spring获取FactoryBean本身的对象是通过在前面加&来完成的;
-创建实例:循环获取beanDefinitionNames中的beanName,根据beanName获取RootBeanDefinition对象(对应),getBean()获取对象,判断是否可实例化(单例非抽象类非LazyInit对象),如果是FactoryBean就获取对象本身getBean(&beanName),不是就检查缓存、父工厂对象、依赖关系及Bean对象类型,根据其类型进行实例化,最后如果是FactoryBean类型就调用getBean(beanName)方法获取目标对象(实际调用的是getObject()方法),不是就直接返回该Bean实例;
(7)触发被监听事件;

2.Ioc容器扩展点
Bean对象有一定扩展性,有哪些扩展点:BeanFactoryPostProcessor、BeanPostProcessor、InitializingBean、DisposableBean、FactoryBean,用户实现这些接口中定义的方法;
调用:spring会在适当的时候调用这些方法,例如BeanFactoryPostProcessor可以在构建BeanFactory时,对Bean进行修正;

3.Spring Bean
由于spring Ioc主要是管理Bean,默认情况下,Bean都是以单例存在isSingleton=true,即getBean()返回的都是同一个对象;相反则isPrototype=true,表示每次getBean()返回的都是一个新的Bean;单例和原型是Bean在一般容器的两种作用域,而在Web容器中,则存在page(页面)、request(Web项目单次请求)、session(HTTP会话)、application(Web项目生命周期)4种,其中page是针对JSP当前页面,因此spring不支持;因此,了解bean在容器中的生命周期很有必要;
定义:
-Resource定位:Ioc根据开发者配置(注解或者XML)进行资源定位;
-BeanDefinition载入:将定位到的信息保存到Bean定义中(BeanDefinition);
-BeanDefinition注册:将BeanDefinition的信息发布到Ioc容器;
初始化,依赖注入:
-lazy-init,默认值default表示false,表示Ioc默认会自动初始化Bean;
-true表示只有当我们使用getBean()获取Bean时,才会进行初始化,完成依赖注入;

整个初始化的步骤详情如下:
-初始化;
-依赖注入;
-setBeanName():需要实现接口BeanNameAware;
-setBeanFactory():需要实现接口BeanFactoryAware;
-setApplicationContext():需要实现接口ApplicationContextAware,其中Ioc容器需要实现ApplicationContext接口才会被调用;
-postProcessBeforeInitialization():BeanPostProcessor的预初始化方法,针对全部Bean而言;
-afterPropertiesSet():需要实现接口InitializingBean;
-自定义初始化方法:可使用XML或注解@PostConstruct标注方法;
-postProcessAfterInitialization():BeanPostProcessor的后初始化方法,针对全部Bean而言;
-生存期;
-destory():需要实现接口DisposableBean,服务器关系或其他关闭Ioc容器事件,会调用;
-自定义销毁方法:可使用XML或注解@PreDestory标注方法,服务器关系或其他关闭Ioc容器事件,会调用;

总之,Ioc就是就是管理Bean及其关系的,可降低对象之间的耦合性;并且我们可以在Ioc的基础上进行扩展,实现自定义需求;

PS:从上文可以看到三个概念,Bean、BeanFactory、FactoryBean,这里也简单做下区分:
(1)Bean是spring中的普通bean,其创建是通过读取配置文件,将所有配置文件信息保存到beandefinition中,在使用getbean的时候通过反射创建实例,然后再将属性值填充;
有3种依赖注入的方式:

public class Role {
	private String id;
	private String name;
	private String note;
	public Role() {}
	public Role(String id, String name, String note) {
		this.id = id;
		this.name = name;
		this.note = note;
	}
	/*getter、setter*/
}

-通过构造器注入:spring采用反射通过构造方法完成注入,不适用于参数多的情况;

<bean id="role" class="cn.infocore.aop.Role">
    <constructor-arg index="0" value="1"/>  //构造器参数
    <constructor-arg index="1" value="name1"/>
    <constructor-arg index="2" value="note1"/>
</bean>

-使用setter方法注入:最主要,需要无参构造器,spring采用反射调用无参构造器生成对象,再采用反射对应的setter注入配置的值;

<bean id="role" class="cn.infocore.aop.Role">
    <property name="id" value="1"/>
    <property name="name" value="name1"/>
    <property name="note" ref="note1"/>
</bean>

-接口注入:主要用于引用外界资源,如通过JNDI获取数据库连接资源;
-使用注解自动装配:注解可以加在属性上,也可以加在set方法上;
@Autowired
private Role role;

(2)FactoryBean:是spring中的工厂bean,是实现了FactoryBean接口的bean;由于普通bean创建的时候只能通过反射,不能自定义bean的创建方式,因而如果有需要自定义bean创建方式的需要的时候,可以使用FactoryBean,指定普通bean的factory-method属性为指定方法即可;除了自定义方式,还有通过FactoryBean接口创建,代码如下,注意其返回的对象不是指定类的一个实例,而是该FactoryBean的getObject方法所返回的对象;如果要获取FactoryBean对象,请在id前面加一个&符号来获取;

public class RoleFactoryBean implements FactoryBean<Role>{
	@Override
	public Role getObject() throws Exception {
		return new Role("1","name1","note1");
	}

	@Override
	public Class<?> getObjectType() {
		return Role.class;
	}

	@Override
	public boolean isSingleton() {
		return false;
	}
}

(3)BeanFactory:创建bean的工厂,BeanFactorty是一个接口,spring中所有对象的创建都围绕着BeanFactory展开,及包含所有Bean;spring中BeanFacroty的实现包括AutowireCapableBeanFactory、DefaultListableBeanFactory、XmlBeanFactory等,通常在springIOC中,会通过beanFactory创建factoryBean;

总之,Bean就是最常见的普通Bean,BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值