SpringIOC实现简述

SpringIOC

IOC的概念我不想赘述,参考《Spring揭秘》一书的具体讲解. 核心就是解耦.

  • IoC容器的职责: 1. 对象的构造 2.对象间依赖管理
  • 好处:解耦主体对象和其依赖的构造逻辑,直接调用依赖的服务即可.
  • Spring中IOC容器包含: 1.BeanFactory 2. ApplicationContext
    前者是父类,后者提供了更丰富的功能.
    前者懒加载,后者相反.
  • ApplicationContext包含了一些非常有用的功能,比如和国际化相关的MessageSource,统一Resource的ResourceLoader和事件监听发布相关的ApplicationEventPublisher
  • WebApplicationContext是ApplicationContext的子类,这主要涉及的就是SpringMVC的功能,这会新开一章
    在这里插入图片描述

xml中的<bean>如何成为spring容器中的对象

xml配置信息是硬盘上的文件,而被运行着的spring容器管理则是被加载到内存中了.
这其中比如涉及很多转化过程.我依照我的理解简单罗列一下:

  • 容器首先要启动,这个启动阶段就有很多事情能做了

    • XxxBeanDefinitionReader读取配置信息,转为BeanDefinition,注册到BeanDefinitionRegistry中
  • 通过容器的getBean()获取实例化后的对象.实例化过程中就会使用BeanDefinition

    • 我们可以在此阶段通过多种途径魔改BeanDefinition,实现接口,xml配置和注解配置皆可.(注意顺序).当然Spring本身也有用到此机制,比如:PropertyPlaceholderConfigurer,PropertyOverrideConfigurer,CustomEditorConfigurer
  • 1.容器启动阶段
    PropertiesBeanDefinitionReader和XmlBeanDefinitionReader是BeanDefinitionReader的两个实现类
    在这里插入图片描述
    这些BeanDefinition会注册到BeanDefinitionRegistry中

  • 2.Bean实例化阶段
    当请求方显式或隐式地调用容器的getBean方法时,容器会检查是否已经初始化,没有的话且存在其对应的BeanDefinition实例时就实例化被请求对象,并为该对象进行依赖注入(DI,这恰恰时IOC容器要做的事情).

  • BeanFactoryPostProcessor允许我们在Bean实例化之前对BeanDefinition进行一些魔改.
    Ordered可以让我们指定顺序.
    BeanFactoryPostProcessor实现类包括PropertyPlaceholderConfigurer , PropertyOverrideConfigurer

  • BeanFactoryPostProcessor实现类之PropertyPlaceholderConfigurer, 对BeanDefinition进行了修改
    在这里插入图片描述在这里插入图片描述在这里插入图片描述

PropertyPlaceholderConfigurer 允许我们在XML中使用占位符来引用上面的文件.
在这里插入图片描述

  • BeanFactoryPostProcessor实现类之PropertyOverrideConfigurer可以允许在properties中覆盖某个属性的值.
  • BeanFactoryPostProcessor实现类之CustomEditorConfigurer,辅助性的将后期可能用到的信息注册到容器中,没有更改BeanDifinition.
    XML或其他类型的配置文件都是字符串,怎么把这些String转变为各种类型?那必然需要转换器,而转换器又首先依赖转换规则,这个类就是来传达这个转换信息的.
    Spring为String到每种对象类型的转换提供一个PropertyEditor,这些PropertyEditors后续会被BeanWrapper使用.

StringArrayPropertyEditor
ClassEditor: Class.forName(String)
FileEditor
LocaleEditor
在这里插入图片描述

Bean实例化的生命周期

Spring框架中的各种*Aware接口
在这里插入图片描述

  1. Bean的实例化与BeanWrapper
    Bean的实例化有不同的方式:反射,cglib动态字节码生成,其他
    在这里插入图片描述
    返回的实例实际是BeanWrapper,如何证明?
    BeanWrapper是一个PropertyAccessor, 以统一的方式对属性进行进行访问.
    还是一个PropertyEditorRegistry,参见BeanFactoryPostProcessor实现类之CustomEditorConfigurer
    在这里插入图片描述
    BeanWrapper的一个优点是方便设置属性(相对反射API而言)
  2. 各种Aware接口,暂且略去
  3. BeanProcessor不是BeanFactoryProcessor,在此阶段可以替换实例,AOP就常常这么干。
    他是spring的一个扩展点
    在这里插入图片描述
    上面Aware接口实际就是通过它来处理的。
    当ApplicationContext中每个对象的实例化过程走到BeanPostProcessor前置处理这一步时,ApplicationContext容器会检测到之前注册到容器的ApplicationContextAwareProcessor这个BeanPostProcessor的实现类,然后就会调用其postProcessBeforeInitialization()方法,检查并设置Aware相关依赖。
    AOP实现可以参考AbstractAutoProxyCreator的该实现方法,用来生成一个代理的对象。
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				this.targetSourcedBeans.add(beanName);
			}
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
	}
  1. 如果实现了InitializaingBean那就调用afterPropertiesSet方法。不过通常不要用,因为要用就得implements 这个接口,显得侵入性比较强。一种更好的方式是XML配置中bean有个属性是init-method,这个例子可以看书上
public interface InitializingBean {
	/**
名字起得挺好,当实例化过程中完成所有属性的设置后才会调用
	 */
	void afterPropertiesSet() throws Exception;

}

  1. 如果实现了DisposableBean 那就调给这个bean注册一个销毁时调用的回调方法。用法同上。
    主要应用场景是数据库连接池的销毁。
    不过这里有个坑,可能不会自动调用,这些细节暂且搁置。
public interface DisposableBean {

	/**
	 * bean销毁的时候会调用,通常就是干一些释放资源的事情
	 */
	void destroy() throws Exception;

}

spring的统一资源加载策略

在这里插入图片描述
11

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值