zoukankan      html  css  js  c++  java
  • Spring工厂方法(factory-bean)配置bean

    spring的世界中, 我们通常会利用bean config file 或者 annotation注解方式来配置bean.

    在第一种利用bean config file(spring xml)方式中, 还包括如下三小类

    1. 反射模式

    2. 工厂方法模式(本文重点)

    3. Factory Bean模式

    其中反射模式最常见, 我们需要在bean 配置中指明我们需要的bean object的全类名。

    例如:

    <bean id="car1" class="com.home.factoryMethod.Car">
      <property name="id" value="1"></property> 
      <property name="name" value="Honda"></property>   
      <property name="price" value="300000"></property> 
    </bean>

    上面bean 里面的class属性就是全类名, Spring利用Java反射机制创建这个bean。

    Factory方法模式

    本文介绍的是另1种模式, 在工厂方法模式中, Spring不会直接利用反射机制创建bean对象, 而是会利用反射机制先找到Factory类,然后利用Factory再去生成bean对象。

    而Factory Mothod方式也分两种, 分别是静态工厂方法 和 实例工厂方法。

    静态工厂方法方式

    所谓静态工厂方式就是指Factory类不本身不需要实例化, 这个Factory类中提供了1个静态方法来生成bean对象

    下面是例子

    bean类Car

    首先我们定义1个bean类Car

    package com.home.factoryMethod;
    
    public class Car {
        private int id;
        private String name;
        private int price;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getPrice() {
            return price;
        }
    
        public void setPrice(int price) {
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Car [id=" + id + ", name=" + name + ", price=" + price + "]";
        }
    
      public Car(){
    
      }
    
      public Car(int id, String name, int price) {
            super();
            this.id = id;
            this.name = name;
            this.price = price;
        }
    }

    然后我们再定义1个工厂类CarStaticFactory

    package com.home.factoryMethod;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class CarStaticFactory {
        private static Map<Integer, Car> map = new HashMap<Integer,Car>();
    
        static{
            map.put(1, new Car(1,"Honda",300000));
            map.put(2, new Car(2,"Audi",440000));
            map.put(3, new Car(3,"BMW",540000));
        }
    
        public static Car getCar(int id){
            return map.get(id);
        }
    }

    里面定义了1个静态的bean 容器map. 然后提供1个静态方法根据Car 的id 来获取容器里的car对象。

    xml配置

      <bean id="bmwCar" class="com.home.factoryMethod.CarStaticFactory" factory-method="getCar">
            <constructor-arg value="3"></constructor-arg>           
        </bean>
    
        <bean id="audiCar" class="com.home.factoryMethod.CarStaticFactory" factory-method="getCar">
            <constructor-arg value="2"></constructor-arg>           
        </bean>

    可以见到, 利用静态工厂方法定义的bean item种, class属性不在是bean的全类名, 而是静态工厂的全类名, 而且还需要指定工厂里的 
    getBean 静态方法名字和参数

    客户端代码

    public static void h(){
      ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-factoryMethod.xml");
      Car car1 = (Car) ctx.getBean("bmwCar");
      System.out.println(car1);
    
      car1 = (Car) ctx.getBean("audiCar");
      System.out.println(car1);
    }

    小结

    由上面的例子, 静态工厂方法方式是非常适用于作为1个bean容器(集合的), 只不过吧bean集合定义在工厂类里面而不是bean config file里面。 
    缺点也比较明显, 把数据写在class里面而不是配置文件中违反了我们程序猿的常识和spring的初衷。当然优点就是令到令人恶心的bean config file更加简洁啦。

    实例工厂方法方式

    所谓实例工厂方式也很容易看懂, 就是里面的getBean 方法不是静态的, 也就是代表要先实例1个工厂对象, 才能依靠这个工厂对象去获得bean 对象。

    用回上面的例子。

    而这次我们写1个实例工厂类

    CarInstanceFactroy

    package com.home.factoryMethod;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class CarInstanceFactory {
        private Map<Integer, Car> map = new HashMap<Integer,Car>();
    
        public void setMap(Map<Integer, Car> map) {
            this.map = map;
        }
    
        public CarInstanceFactory(){
        }
    
        public Car getCar(int id){
            return map.get(id);
        }
    }

    bean xml写法

     <bean id="carFactory" class="com.home.factoryMethod.CarInstanceFactory">
            <property name="map">
                <map>
                    <entry key="4">
                            <bean class="com.home.factoryMethod.Car">
                                <property name="id" value="4"></property>   
                                <property name="name" value="Honda"></property> 
                                <property name="price" value="300000"></property>   
                            </bean>
                    </entry>    
    
                    <entry key="6">
                            <bean class="com.home.factoryMethod.Car">
                                <property name="id" value="6"></property>   
                                <property name="name" value="ford"></property>  
                                <property name="price" value="500000"></property>   
                            </bean>
                    </entry>
                </map>  
            </property>
         </bean>
    
         <bean id="car4" factory-bean="carFactory" factory-method="getCar">
            <constructor-arg value="4"></constructor-arg>           
         </bean>
    
         <bean id="car6" factory-bean="carFactory" factory-method="getCar">
            <constructor-arg value="6"></constructor-arg>           
         </bean

    因为实例工厂本身要实例化, 所以我们可以在xml中 指定它里面容器的data, 解决了上面提到的静态工厂方法的缺点啦

    client代码

    public static void h2(){
            ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-factoryMethod.xml");
            Car car1 = (Car) ctx.getBean("car4");
            System.out.println(car1);
    
            car1 = (Car) ctx.getBean("car6");
            System.out.println(car1);
        }

    小结

    实例工厂方式使用起来更加灵活, FactoryBean比起工厂方法方式更加常见。

  • 相关阅读:
    userAgent判断当前设备类型
    h5+css3最简单的图片飞入以及淡入淡出效果
    ruby的form中常用的控件
    初识swipe.js
    后缀为7z的文件解码
    python all()函数
    flask web表单
    flask过滤器
    flask学习笔记1.21
    py学习笔记1.13、1.14
  • 原文地址:https://www.cnblogs.com/cowboys/p/6638484.html
Copyright © 2011-2022 走看看