迄今为止,所接触到的Bean都是“无知觉”的,就像黑客帝国中机械工厂里面“养殖”的人类,他们虽然能完成必定的功能,可是根本不知道本身在工厂(BeanFactory)中的代号(id),或者本身是在哪一个工厂(BeanFactory的引用)中沉睡。因此,本节的目的就是要创造出一个尼奥同样的Bean,让他知道本身在工厂中的id和本身原来躺在哪一个工厂中。这里,称之为,Bean对Spring有知觉。程序员
可是有言在先,若是要在Spring容器中作到这两点,固然,能够本身经过某些方法实现,代价是大量冗余代码,好处是跟Spring解耦。若是使用Spring提供的接口,好处固然减小代码的规模,“缺点”(若是算的话)是与Spring耦合。总之,不管采起那种办法仍是要看实际须要。this
/////////////////////
让Bean对Name有知觉
/////////////////////spa
做用:让Bean获取本身在BeanFactory配置中的名字(根据状况是id或者name)。接口
实现:经过实现BeanNameAware接口,接口中就一个方法setBeanName()生命周期
例程以下(P100,代码清单5-11,部分)
public class LogginBean implements BeanNameAware {
private String beanName = null;
public void setBeanName(String beanName) {
this.beanName = beanName;
}
}内存
额外说明:
Spring自动调用。而且会在Spring自身完成Bean配置以后,且在调用任何Bean生命周期回调(初始化或者销毁)方法以前就调用这个方法。换言之,在程序中使用BeanFactory.getBean(String beanName)以前,Bean的名字就已经设定好了。因此,程序中能够尽情的使用BeanName而不用担忧它没有被初始化。get
固然,Bean之中必定要有个String类型变量来保存BeanName的值,这个是在编写Bean代码时有程序员手工完成的,而不是经过什么特殊的饿配置。io
一般都是为了更好的饿配置Log,可是请注意,不要只是由于配合Log就把bean那么中添加任何业务含义,不然会让你本身的类关联到某个Spring特性上去,而它带来的好处倒是微不足道的。若是确实须要Bean带有某种内部名称,那么最好让Bean本身实现某个方法,例如setName(),而后使用DI给每一个Bean注入一个名字,这样技能保持配置Bean的名字仍然可以简洁,且你也无需修改本身的配置文件,好让Bean的名字带有业务含义。class
////////////////////////////////
让Bean对工厂有知觉
////////////////////////////////容器
做用:让Bean获取配置他们的BeanFactory的引用。
实现:实现BeanFactoryAware接口,其中只有一个方法即setFactory(BeanFactory factory)。使用上与BeanNameAware接口无异,只不过BeanFactoryAware注入的是个工厂,BeanNameAware注入的是个Bean的名字。
额外说明:
虽然原书中并未说起setFactory()方法的调用时机,可是能够猜测到,这个方法多是在根据某个配置文件建立了一个新工厂以后,Spring才调用这个方法,并把BeanFactory注入到Bean中。
让bean获取配置本身的工厂以后,固然能够在Bean中使用这个工厂的getBean()方法,可是,实际上很是不推荐这样作,由于结果是进一步加大Bean与Spring的耦合,并且,能经过DI注入进来的尽可能经过DI来注入。
固然,除了查找bean,BeanFactory能够提供大量其余的功能,例如销毁singleton模式的Bean。
补充说明: factory.preInstantiateSingletons();方法。preInstantiateSingletons()方法当即实例化全部的Bean实例,有必要对这个方法和Spring加载bean的机制作个简单说明。 方法自己的目的是让Spring当即处理工厂中全部Bean的定义,而且将这些Bean所有实例化。由于Spring默认实例化Bean的状况下,采用的是lazy机制,换言之,若是不经过getBean()方法(BeanFactory或者ApplicationContext的方法)获取Bean的话,那么为了节省内存将不实例话Bean,只有在Bean被调用的时候才实例化他们。