创世纪:spring之初(第三日)

  johnson将spring的主框架与运行流程创造完毕之后,发觉spring中提供了许多灵活扩展的地方。于是johnson准备在第三日将这些灵活扩展的用法公布出来。

  1. BeanPostProcessor。BeanPostProcessor提供了bean创建完成后的扩展接口,当你需要在bean创建完后对其做一定处理,则BeanPostProcessor是首选的方式。

  2. Aware。注入的bean需要了解其容器的某些部分,spring通过Aware完成回调,如BeanNameAware,可以让bean得知自己的名字, BeanFactoryAware可以让bean了解到BeanFactory, ApplicationContextAware,可以让bean操作ApplicationContext。通过这种方式,注入spring的bean能够做更加广泛的事情。

  对于BeanPostProcessor的扩展,spring自身有一个例子,即如何识别Aware bean的例子。Aware bean是比较特殊的bean,需要spring对其额外注入一些属性,那么注入的过程spring会怎么做呢?实际上spring并没有将他写在核心的处理过程里面,而是放到了ApplicationContextAwareProcessor这个BeanPostProcessor,通过BeanPostProcessor的postProcessBeforeInitialization最终invokeAwareInterfaces以判断该bean的类型并注入相应的属性。这种做法利用了BeanPostProcessor完成了另一个扩展用法,实在是高超。

private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
						new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

  关于Aware的用法则更多了,比如如下代码能够感知ApplicationContext,spring在创建完这个bean之后便会注入ApplicationContext,于是我们就可以使用该context完成事件发布。

public class HelloBean implements ApplicationContextAware {  
  
    private ApplicationContext applicationContext;  
    private String helloWord = "Hello!World!";  
  
    public void setApplicationContext(ApplicationContext context) {  
        this.applicationContext = context;  
    }  
  
    public void setHelloWord(String helloWord) {  
        this.helloWord = helloWord;  
    }  
  
    public String getHelloWord() {  
        applicationContext.publishEvent(  
               new PropertyGettedEvent("[" + helloWord + "] is getted"));  
        return helloWord;  
    }  
}  
  3. BeanFactoryPostProcessor,这个PostProcessor通常是用来处理在BeanFactory创建后的扩展接口。一个例子如下,当注入这个bean以后,它便会在BeanFactory创建完毕自动打印注入的bean数量:

public class BeanCounter implements BeanFactoryPostProcessor{

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
			throws BeansException {
		System.out.println(beanFactory.getBeanDefinitionCount());
	}
	
}
   4. FactoryBean。FactoryBean是一种特殊的bean,这种bean允许注入到spring容器并用其生成真正的bean,所以可以这样定义,FactoryBean本身是一种bean,这种bean又有能够提供bean的能力。下面从FactoryBean的调用开始,讲到spring是如何使用这个bean的。

   要想区分普通bean和FactoryBean,spring也必须有判断他们并特殊处理的过程,这个过程就在AbstractBeanFactory的getObjectForBeanInstance中

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
			throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
		}

		// Now we have the bean instance, which may be a normal bean or a FactoryBean.
		// If it's a FactoryBean, we use it to create a bean instance, unless the
		// caller actually wants a reference to the factory.
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd == null) {
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}
  可以看出来,如果是普通bean,就直接返回了,而如果是FactoryBean,最终调用会调用factory.getObject从而返回具体对象。如果将整个spring看做一个抽象工厂,生产抽象的bean时,则FactoryBean就是具体工厂,生产你需要的对象。

  spring中FactoryBean用法很多,举个比较常见的例子,集成hibernate的sessionFactory时一般会注入LocalSessionFactoryBean,但是这个sessionFactory实际上不是普通的bean,可以简单在配置文件中注入就能生产,它有很多定制的部分,于是spring让这个bean成为一个FactoryBean并控制其生产的对象。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值