• BeanFactory与FactoryBean


     

    区别:BeanFactory是个Factory,也就是IOC容器或对象工厂,负责生产和管理bean, spring容器对该接口有多种实现,如:DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,其中XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似,即可以自定义实现bean的实例化过程

    生成一个普通的bean类

    /**
    * @author MM
    * @create 2018-08-06 15:32
    **/
    public class Car {

    String name;


    public Car() {
    }

    public Car(String name) {
    this.name = name;
    }

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }


    public void run() {
    System.out.println(this.name + " is running");
    }

    }

    如果是直接通过BeanFactory实例化只需要简单配置

    <bean id= "car" class = "com.deam.entity.Car">

      <property name="name" value =  "beanFactory"></property>

    </bean>

     然后通过spring容器实例化

            ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
            BeanFactory factory = (BeanFactory) ctx;
    
            Car car1 = (Car) factory.getBean("car");
            car1.run();

    日志显示:

    八月 06, 2018 4:43:56 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@17ed40e0: startup date [Mon Aug 06 16:43:56 CST 2018]; root of context hierarchy
    八月 06, 2018 4:43:56 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [beans.xml]
    beanFactory is running
    
    Process finished with exit code 0

    通过FactoryBean 实例化,创建一个bean实现FactoryBean接口重写getObject方法

    /**
     * @author MM
     * @create 2018-08-06 16:29
     **/
    public class CarFactoryBean implements FactoryBean<Car> {
    
        String carInfo;
    
        public String getCarInfo() {
            return carInfo;
        }
    
        public void setCarInfo(String carInfo) {
            this.carInfo = carInfo;
        }
    
        @Nullable
        @Override
        public Car getObject() throws Exception {
    
            Car car = new Car(carInfo);
    
            return car;
        }
    
        @Nullable
        @Override
        public Class<?> getObjectType() {
            return null;
        }
    
        @Override
        public boolean isSingleton() {
            return false;
        }
    }

    配置容器实例化FactoryBean

    <bean id="car" class="com.demo.util.CarFactoryBean">
    <property name="carInfo" value="factoryBean"></property>
    </bean>
            ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
            BeanFactory factory = (BeanFactory) ctx;
    
            Car car1 = (Car) factory.getBean("car");
            car1.run();
            Car car2 = (Car) factory.getBean("car");
            System.out.println("car1==car2 is " + (car1 == car2));
    
            CarFactoryBean factoryBean = (CarFactoryBean) factory.getBean("&car");
            System.out.println(factoryBean.getCarInfo());

    日志显示:

      

    八月 06, 2018 4:48:57 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@17ed40e0: startup date [Mon Aug 06 16:48:57 CST 2018]; root of context hierarchy
    八月 06, 2018 4:48:57 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [beans.xml]
    factoryBean is running
    car1==car2 is false
    factoryBean

    当调用getBean("car")时,Spring通过反射机制发现CarFactoryBean实现了FactoryBean的接口,这时Spring容器就调用接口方法CarFactoryBean#getObject()方法返回。如果希望获取CarFactoryBean的实例,则需要在使用getBean(beanName)方法时在beanName前显示的加上"&"前缀:如getBean("&car");

    1、FactoryBean与factory-bean的作用都是通过其他的一个bean工厂产生一个真实的bean,不同的是,FactoryBean是使用了spring默认的接口,具有一定侵入性,对框架造成依赖,factory-bean不会改变代码接口,属于注入方式。spring中很多类似的组队,比如init-method和InitializingBean。

    2、从原则上,我们使用spring,很大的优点在于它没有侵略性。那么为什么会提供接口形式呢。接口形式更倾向于框架的使用,比如spirng的另一个重要的特性AOP,框架编写了AOPFactoryBean,我们不需要知道他内部实现,也不会获取他的实力,只需要配置它需要代理的类和接口,便可以成功返回一个真实的bean,也就是目标类的代理类,从而完成各种工作。

    3、可以说spirng的很多扩展工作都是基于预留接口提供,同时新扩展的功能也会提供新的预留接口,比如aop的切面等。

  • 相关阅读:
    docker 安装部署 mysql(配置文件启动)
    mac Charles抓包
    docker 安装部署 redis(配置文件启动)
    安装mysql5.6
    Linux命令
    git命令汇总
    Java程序占用的内存可能会大于Xmx
    排序
    二分查找
    Elasticsearch核心技术(一):Elasticsearch环境搭建
  • 原文地址:https://www.cnblogs.com/gcm688/p/9430458.html
Copyright © 2020-2023  润新知