• 理解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工厂
        }
    }
  • 相关阅读:
    Angular基础(三) TypeScript
    Angular基础(二) 组件的使用
    Angular 2基础(一) 环境搭建
    Web API 方法的返回类型、格式器、过滤器
    WebAPI路由、参数绑定
    《ASP.NET MVC企业实战》(三)MVC开发前奏
    《ASP.NET MVC企业实战》(二) MVC开发前奏
    《ASP.NET MVC企业实战》(一) MVC开发前奏
    《Inside C#》笔记(完) 程序集
    巨杉数据库助力民生银行、广发银行前台智慧化业务
  • 原文地址:https://www.cnblogs.com/yixianyixian/p/8404189.html
Copyright © 2020-2023  润新知