Spring4的介绍02-spring的工厂类

1. Spring工厂类的结构图

2 BeanFactory接口

        在spring容器中,BeanFactory接口是IOC容器要实现的最基础的接口,定义了管理bean的最基本的方法,例如获取实例、基本的判断等。

BeanFactory有多个子接口来进一步扩展bean相关的功能,其中两个比较重要的与本文有关系的工厂类

2.1 HierarchicalBeanFactory

beanFactory可以设置ParentBeanFactory,这个接口的两个方法都是和ParentBeanFactory相关的

1. getParentBeanFactory方法返回ParentBeanFactory

2. containsBean,containsBean方法找不到bean的时候会通过ParentBeanFactory去找

3. containsLocalBean方法是相对containsBean方法而言的,只在当前beanFactory找

2.2 ListableBeanFactory

主要用于获取bean相关信息,例如获取所有bean名称,查找指定类型的所有bean等

3 ApplicationContext接口

           通过spring工厂类结构图,我们可以知道ApplicationContext继承了BeanFactory接口,通过在eclipse中查看BeanFactory接口,我们可以知道ApplicationContext也继承了HierarchicalBeanFactory和ListableBeanFactory,其还继承了诸如Environment、Resource、Message、Event 等相关的接口。

         也就是说除了bean的管理配置相关的能力,ApplicationContext还拥有了Environment(环境)、MessageSource(国际化)、ResourceLoader(资源)、ApplicationEventPublisher(应用事件)等服务相关的接口。

         简单的说ApplicationContext是以bean管理为基础的综合能力扩展,用于满足业务对Spring综合能力的需要;
applicationContext接口也有两个重要的实现类

3.1 ClassPathXmlApplicationContext

用于加载类路径下的配置文件,类路径可以理解为就是src路径,src目录最终会被翻译到WEB-INF下的classes下,就是类路径下。

3.2 FileSystemXmlApplicationContext

用于加载文件系统下的配置文件,即某个硬盘下的配置文件。

例如:如果我们将applicationcontext.xml配置文件放到了其他的目录,比方说F盘,这时候,我们要使用FileSystemXmlApplicationContext来创建工厂对象。

ApplicationContext application1 = new FileSystemXmlApplicationContext("F://applicationContext.xml");

4 小结

4.1  BeanFactory

1. BeanFactory是基础,BeanFactory和它的子接口定义的API满足了spring环境中对bean管理和配置的需求;

2. BeanFactory在调用getBean的时候,才会生成类的实例

例如:在调用getBean的时候,才会帮我们创建UserDao的实例对象

UserDao bean = (UserDao)application.getBean("userDao");


4.2 ApplicationContext

1. ApplicationContext是扩展,以BeanFactory为主线,通过继承的方式综合了环境、国际化、资源、事件等多条支线,自己又规定了一些扩展服务(如返回context的id,应用名称等),而所有支线都以bean服务为基础;

2. ApplicationContext在加载配置文件的时候,就会将spring所管理的类都实例化。

例如:在加载配置文件的时候,spring就会将其管理的单例模式创建的类都实例化

即程序执行

ApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml");

 的时候,就会加载xml配置文件,然后实例化bean对象

<bean id="userDao" class="com.itcast.spring.demo1.UserDaoImpl">
    	<property name="name" value="lisi"></property>
    </bean>

5. 扩展阅读

5.1 ApplicationContext源码

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
        MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

    //标识当前context实例的id,最终会通过native方法来生成:System.identityHashCode
    String getId();

    //返回该context所属的应用名称,默认为空字符串,在web应用中返回的是servlet的contextpath 
    String getApplicationName();

    //返回当前context的名称
    String getDisplayName();

    //返回context第一次被加载的时间
    long getStartupDate();

    //返回该context的parent
    ApplicationContext getParent();

    //返回具有自动装配能力的beanFactory,默认返回的就是初始化时实例化的beanFactory
    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}


5.2 实现类解析

如果有个类实现了ApplicationContext接口,就必须实现上述多个接口定义的方法,这个类岂不是很复杂?我们看看AbstractApplicationContext类的源码,这是个基础抽象类,常用的ClassPathXmlApplicationContext、AnnotationConfigServletWebServerApplicationContext等都继承自AbstractApplicationContext。

先看看是如何实现BeanFactory接口中定义的方法的:

@Override
    public Object getBean(String name) throws BeansException {
        assertBeanFactoryActive();
        return getBeanFactory().getBean(name);
    }

    @Override
    public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
        assertBeanFactoryActive();
        return getBeanFactory().getBean(name, requiredType);
    }

    @Override
    public <T> T getBean(Class<T> requiredType) throws BeansException {
        assertBeanFactoryActive();
        return getBeanFactory().getBean(requiredType);
    }

    @Override
    public Object getBean(String name, Object... args) throws BeansException {
        assertBeanFactoryActive();
        return getBeanFactory().getBean(name, args);
    }

    @Override
    public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
        assertBeanFactoryActive();
        return getBeanFactory().getBean(requiredType, args);
    }

    @Override
    public boolean containsBean(String name) {
        return getBeanFactory().containsBean(name);
    }

    @Override
    public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        assertBeanFactoryActive();
        return getBeanFactory().isSingleton(name);
    }

    @Override
    public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
        assertBeanFactoryActive();
        return getBeanFactory().isPrototype(name);
    }

    @Override
    public boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException {
        assertBeanFactoryActive();
        return getBeanFactory().isTypeMatch(name, targetType);
    }

    @Override
    public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        assertBeanFactoryActive();
        return getBeanFactory().getType(name);
    }

    @Override
    public String[] getAliases(String name) {
        return getBeanFactory().getAliases(name);
    }

看过上述代码后恍然大悟,原来AbstractApplicationContext并没有自己来完成bean的管理配置,而是全部委托给了getBeanFactory()方法返回的这个实例,接口是组合,实现也是组合,这种清晰的设计是学习典范;

再来看看getBeanFactory()方法,解释究竟是谁在真正的提供bean的管理配置服务,该方法的实现在AbstractApplicationContext的子类AbstractRefreshableApplicationContext中,代码很简单,返回了成员变量beanFactory:

public final ConfigurableListableBeanFactory getBeanFactory() {
        synchronized (this.beanFactoryMonitor) {
            if (this.beanFactory == null) {
                throw new IllegalStateException("BeanFactory not initialized or already closed - " +
                        "call 'refresh' before accessing beans via the ApplicationContext");
            }
            return this.beanFactory;
        }
    }

该成员变量在refreshBeanFactory方法中实例化,而refreshBeanFactory方法又是在spring容器初始化的时候调用的,所以容器初始化之后,AbstractApplicationContext就具备了bean管理配置的能力;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值