zoukankan      html  css  js  c++  java
  • spring4之依赖注入的三种方式

    1、Setter注入

            <bean id="helloWorld" class="com.jdw.spring.beans.HelloWorld">
    		<property name="name" value="Spring"></property>
    	</bean>
    

      从这个最简单的配置可以得出以下两个结论:一、class属性需要全类名进行配置,说了ioc容器是通过反射进行创建bean的;二、bean类必须有默认的构造函数

      这种通过property子元素进行属性配置的方式是spring依赖注入的三大方式之一:setter注入。

    2、构造器注入

             <bean id="car" class="com.jdw.spring.beans.Car">
    		<constructor-arg value="audi" type="java.lang.String"></constructor-arg>
    		<constructor-arg type="java.lang.String">
    			<!-- 对于包含特殊字符的属性值,可以在value子节点使用CDATA -->
    			<value><![CDATA[<shanghai>]]></value>
    		</constructor-arg>
    		<constructor-arg type="int">
    			<value>240</value>
    		</constructor-arg>
    	</bean>
    

      构造器注入,言外之意,需要在bean之中配置构造器,可以不需要默认构造方法,但是必须保证构造器参数与配置文件中的参数数量和类型一致

    	<bean id="car1" class="com.jdw.spring.beans.Car">
    		<constructor-arg value="audi" index="0" type="java.lang.String"></constructor-arg>
    		<constructor-arg value="shanghai" index="1" type="java.lang.String"></constructor-arg>
    		<constructor-arg value="200000" index="2" type="double"></constructor-arg>
    	</bean>
    

      对于有多个构造器的bean,可通过上述的index和type属性进行配置,以区别重载的构造器

    3、工厂方法注入

        工厂方法注入又分为静态工厂方法注入和实例工厂方法注入

        (1)静态工厂方法注入

        一个模拟的简单静态工厂如下,该静态工厂提供了一个静态方法getCar,调用该方法则返回一个Car实例,注意红色注释,如果配置文件中scope=singleton,采用静态工厂方法注入获得的bean是否为单例呢?

    public class StaticCarFactory {
    
    	public static Map<String,Car> cars=new HashMap<>();
    	static{
    		cars.put("audi", new Car("audi",300000));
    		cars.put("bmw", new Car("bmw",200000));
    		cars.put("hongqi", new Car("hongqi",600000));
    	}
    	public static Car getCar(String name){
    		//return new Car("audi",300000);//如果这么写,那么获得的car实例还是单例的么?
    		return cars.get(name);
    	}
    }
    

      静态工厂注入配置:

            <bean id="car" class="com.jdw.spring.factory.StaticCarFactory"
    		factory-method="getCar">
    		<constructor-arg value="audi"></constructor-arg>
    	</bean>
    

        说明:所谓静态工厂方法注入,不过是通过一个静态方法创建bean的实例,注意,在singelton情况下该静态方法只会在ioc容器初始化bean时调用一次,即不管getBean("car")多少次,都是返回的同一个Car对象。而在prototype情况下,getBean("car")调用一次就会对应的调用一次静态方法getCar。从这里可以更好的理解singleton和prototype的区别,前者会在ioc容器初始化时创建,后者则在用户调用时再创建。

        (2)实例工厂方法注入

      实例工厂代码:

    public class InstanceCarFactory {
    	private Map<String, Car> cars = null;
    
    	public InstanceCarFactory() {
    		cars = new HashMap<>();
    		cars.put("audi", new Car("audi", 30000));
    		cars.put("BMW", new Car("audi", 20000));
    		cars.put("HQ", new Car("audi", 50000));
    	}
    
    	public Car getCar(String brand) {
    		return cars.get(brand);
    	}
    }
    

      实例工厂的getCar为非静态,这就导致,必须先实例化该工厂,即需要配置该工厂的bean。

            <!-- 配置实例工厂 -->
    	<bean id="carFactory" class="com.jdw.spring.factory.InstanceCarFactory"></bean>
    
    	<!-- 通过实例工厂配置bean -->
    	<bean id="car1" factory-bean="carFactory" factory-method="getCar">
    		<constructor-arg name="brand" value="audi"></constructor-arg>
    	</bean>
    

      学而不思则罔,通过Setter注入和构造器注入可以很方便快捷的配置bean,静态工厂注入和实例工厂注入到底是为了那样?难道只是为了支持下工厂模式?spring你别逗好么,咱自己不就相当于一个超级bean工厂么!那干嘛还弄给工厂方法注入呢?一定有其原因。

          有一家手机卖场,只卖A、B、C三种手机,假设顾客只关心价格price和参数信息info,那么问题来了,一个顾客进入卖场,说:我要买A手机。手机卖场(IOC)需要初始化一个A的Bean。又一个顾客进入卖场,说:我要B手机。手机卖场也得初始化一个B的bean。同样,也得初始化C的bean。三个手机还好些,IOC就建立三个bean,那么10种手机呢?每种手机的info需要特殊处理呢?比如手机参数信息要有一系列的运算统计信息呢?这样看来IOC貌似不适合把每个bean都放在配置文件里,也不适合建立多个bean。

      解决方案就是,建立一个手机bean,通过工厂注入(静态工厂、实例工厂都可以),传入手机类型名称,获得对应的手机,只是要把bean配置为prototype,这样运行时就可以获取各式各样的手机了!

         那静态工厂和实例工厂两种注入方式,除了配置的不同,在应用上有什么区别么?

      

      

  • 相关阅读:
    codeforce 266c Below the Diagonal 矩阵变换 (思维题)
    8月21日训练日记
    CodeForces 651B Beautiful Paintings
    CodeForces 651 C Watchmen
    CodeForces 17D Notepad(同余定理)
    CodeForces 19B Checkout Assistant
    Code Forces 18D Seller Bob(简单DP)
    HOJ Recoup Traveling Expenses(最长递减子序列变形)
    ZOJ 3469Food Delivery(区间DP)
    Code Forces 149DColoring Brackets(区间DP)
  • 原文地址:https://www.cnblogs.com/sdnu/p/5309387.html
Copyright © 2011-2022 走看看