zoukankan      html  css  js  c++  java
  • 理解spring中的BeanFactory和FactoryBean的区别与联系

    原文地址:http://blog.csdn.net/joenqc/article/details/66479154

    首先,这俩都是个接口…

    实现 BeanFactory 接口的类表明此类事一个工厂,作用就是配置、新建、管理 各种Bean。

    而 实现 FactoryBean 的类表明此类也是一个Bean,类型为工厂Bean(Spring中共有两种bean,一种为普通bean,另一种则为工厂bean)。顾名思义,它也是用来管理Bean的,而它本身由spring管理。

    一个Bean想要实现 FactoryBean ,必须实现以下三个接口:

    1. Object getObject():返回由FactoryBean创建的Bean的实例
    
    2. boolean isSingleton():确定由FactoryBean创建的Bean的作用域是singleton还是prototype;
    
    3. getObjectType():返回FactoryBean创建的Bean的类型。
    • 1
    • 2
    • 3
    • 4
    • 5

    有一点需要注意,如果将一个实现了FactoryBean的类成功配置到了spring上下文中,那么通过该类对象的名称(比如appleFactoryBean)从spring的applicationContext或者beanFactory获取bean时,获取到的是appleFactoryBean创建的apple实例,而不是appleFactoryBean自己,如果想通过spring拿到appleFactoryBean,需要在名称前加 & 符号 :

    out.println(applicationContext.getBean("&appleFactoryBean"))
    • 1

    这个prefix在BeanFactory接口源码中有提到:

    /**
    * Used to dereference a {@link FactoryBean} instance and distinguish it from
    * beans <i>created</i> by the FactoryBean. For example, if the bean named
    * {@code myJndiObject} is a FactoryBean, getting {@code &myJndiObject}
    * will return the factory, not the instance returned by the factory.
    */
        String FACTORY_BEAN_PREFIX = "&";
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    还有一点需要注意,FactoryBean管理的bean实际上也是由spring进行配置、实例化、管理,因此由FactoryBean管理的bean不能再次配置到spring配置文件中(xml、java类配置、注解均不可以),否则会报如下异常:

    Exception in thread "main" org.springframework.beans.factory.BeanIsNotAFactoryException: Bean named 'appleFactoryBean' is expected to be of type 'org.springframework.beans.factory.FactoryBean' but was actually of type 'java.lang.Object'
        at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1612)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:317)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:742)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
        at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
        at com.joen.testspringcontainer.Start.main(Start.java:11)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    附上一个例子:

    spring配置类:

    @Configuration
    @ComponentScan
    public class Configurations {
    }
    • 1
    • 2
    • 3
    • 4

    AppleBean :

    //@Component  这里不可以加注解 !!!!!!
    public class AppleBean{
    
    }
    • 1
    • 2
    • 3
    • 4

    AppleFactoryBean :

    @Component
    public class AppleFactoryBean implements FactoryBean{
    
        public Object getObject() throws Exception {
            return new AppleBean();
        }
    
        public Class<?> getObjectType() {
            return AppleBean.class;
        }
    
        public boolean isSingleton() {
            return false;
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    启动类 :

    public class Start {
        public static void main(String[] args){
            ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Configurations.class);
                     out.println(applicationContext.getBean("appleFactoryBean"));//得到的是apple
                     out.println(applicationContext.getBean("&appleFactoryBean"));//得到的是apple工厂
        }
    }
  • 相关阅读:
    面向接口程序设计思想实践
    Block Chain Learning Notes
    ECMAScript 6.0
    Etcd Learning Notes
    Travis CI Build Continuous Integration
    Markdown Learning Notes
    SPRING MICROSERVICES IN ACTION
    Java Interview Questions Summary
    Node.js Learning Notes
    Apache Thrift Learning Notes
  • 原文地址:https://www.cnblogs.com/yixianyixian/p/8404189.html
Copyright © 2011-2022 走看看