白话Spring源码(八):Aware接口

我们知道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.springframework.beans.factory.support.DefaultListableBeanFactory@3dc0bb: defining beans [hello]; root of factory hierarchy

猜你喜欢

转载自blog.csdn.net/haoxin963/article/details/85079036
今日推荐