白話Spring原始碼(八):Aware介面
阿新 • • 發佈:2018-12-23
我們知道spring框架中所有bean都是在工廠裡建立的,bean對自己是“無知覺”的,不知道自己叫什麼名字(bean的id或者name),從哪裡來(哪個工廠建立)。
一、為什麼需要Aware
大家看過黑客帝國電影吧,黑客帝國中機械工廠裡面“養殖”的人類,他們雖然能完成一定的功能,但是根本不知道自己在工廠(BeanFactory)中的代號(id),或者自己是在哪個工廠(BeanFactory的引用)中沉睡。所以,本節的目的就是要創造出一個尼奧一樣的Bean,讓他知道自己在工廠中的id和自己原來躺在哪個工廠中。
這裡,稱之為,Bean對Spring有知覺(Aware翻譯過來就是知覺)。
二、Aware是怎麼實現的
在spring1.0中定義了兩個介面BeanNameAware和BeanFactoryAware 介面。
BeanNameAware:讓Bean獲取自己在BeanFactory配置中的名字(根據情況是id或者name)
public interface BeanNameAware { /** * Set the name of the bean in the bean factory that created this bean. * <p>Invoked after population of normal bean properties but before an init * callback like InitializingBean's afterPropertiesSet or a custom init-method. * @param name the name of the bean in the factory */ void setBeanName(String name); }
BeanFactoryAware :讓Bean獲取配置他們的BeanFactory的引用。
public interface BeanFactoryAware { /** * Callback that supplies the owning factory to a bean instance. * <p>Invoked after population of normal bean properties but before an init * callback like InitializingBean's afterPropertiesSet or a custom init-method. * @param beanFactory owning BeanFactory (may not be null). * The bean can immediately call methods on the factory. * @throws BeansException in case of initialization errors * @see BeanInitializationException */ void setBeanFactory(BeanFactory beanFactory) throws BeansException; }
我們只需實現這個介面,就可以獲取bean的名稱或者bean工廠的例項,那怎麼做到的呢,我們再來看一下工廠獲取bean的原始碼:
protected Object createBean(String beanName, RootBeanDefinition mergedBeanDefinition) throws BeansException {
//省略其他程式碼
//注意:這個就會Aware實現的原始碼
try {
if (bean instanceof BeanNameAware) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking setBeanName() on BeanNameAware bean '" + beanName + "'");
}
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanFactoryAware) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking setBeanFactory() on BeanFactoryAware bean '" + beanName + "'");
}
((BeanFactoryAware) bean).setBeanFactory(this);
}
//省略其他程式碼
}
看到沒有,其實很簡單嘛!
三、demo
1、beanNameAware介面:
package com.pb.entity;
import org.springframework.beans.factory.BeanNameAware;
/*
* 實體類實現init方法和BeanNameAware介面
*/
public class Hello implements BeanNameAware{
@Override
public void setBeanName(String arg0) {
System.out.println("回撥setBeanName方法 id屬性是"+arg0);
}
public void init(){
System.out.println("正在執行初始化方法init");
}
}
applicationContext.xml
<bean id="hello" class="com.pb.entity.Hello" init-method="init"></bean>
測試類:
package com.pb.demo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.pb.entity.Hello;
public class HelloTest {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
Hello hello=context.getBean("hello",Hello.class);
}
}
結果:
回撥setBeanName方法 id屬性是hello
正在執行初始化方法init
2、BeanFactoryAware介面:
package com.pb.entity;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
/*
* 實體類實現init方法和BeanNameAware介面
*/
public class Hello implements BeanNameAware,BeanFactoryAware{
private BeanFactory bf;
@Override
public void setBeanName(String arg0) {
System.out.println("回撥setBeanName方法 id屬性是"+arg0);
}
public void init(){
System.out.println("正在執行初始化方法init");
}
/*
* 重寫setBeanFactory方法
* @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
*/
@Override
public void setBeanFactory(BeanFactory arg0) throws BeansException {
this.bf=arg0;
}
public BeanFactory getBf() {
return bf;
}
}
配置檔案不變
測試類:
package com.pb.demo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.pb.entity.Hello;
public class HelloTest {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
Hello hello=context.getBean("hello",Hello.class);
System.out.println("得到beanFactory物件 "+hello.getBf());
}
}
結果:
回撥setBeanName方法 id屬性是hello
正在執行初始化方法init
得到beanFactory物件 org.s[email protected]3dc0bb: defining beans [hello]; root of factory hierarchy