瑞安天气:Spring中bean的四种注入方式

2020-05-12 10 views 0

扫一扫用手机浏览

一、前言

  最近在温习Spring的相关内容,这篇博客就来纪录一下Springbean的属性注入值的四种方式。这篇博客主要解说在xml文件中,如作甚bean的属性注入值,最后也会简朴提一下使用注解的方式。空话不多说,直接最先吧。


二、正文

2.1 注入方式

  在Spring中,共有四种方式为bean的属性注入值,划分是:

  • set方式注入
  • 组织器注入
  • 静态工厂注入
  • 实例工厂注入

  下面我就划分演示一下,若何使用这四种方式举行属性的注入。


2.2 set方式注入

  在演示前,我们需要准备几个类,我使用下面两个类来举行注入的演示,这两个类划分是UserCAR类:

public class Car {
    // 只包罗基本数据类型的属性
    private int speed;
    private double price;
    
    public Car() {
    }
    public Car(int speed, double price) {
        this.speed = speed;
        this.price = price;
    }
    
    public int getSpeed() {
        return speed;
    }
    public void setSpeed(int speed) {
        this.speed = speed;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    @Override
    public String toString() {
        return "Car{" +
                "speed=" + speed +
                ", price=" + price +
                '}';
    }
}

public class User {
	
    private String name;
    private int age;
    // 除了上面两个基本数据类型的属性,User还依赖Car
    private Car car;
    
    public User() {
    }
    public User(String name, int age, Car car) {
        this.name = name;
        this.age = age;
        this.car = car;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Car getCar() {
        return car;
    }
    public void setCar(Car car) {
        this.car = car;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", car=" + car +
                '}';
    }
}

  有了上面两个类,我们就可以演示set注入了。需要注重一点,若是我们需要使用set注入,那么必须要为属性提供set方式,Spring容器就是通过挪用beanset方式为属性注入值的。而在xml文件中,使用set注入的方式就是通过property标签,如下所示:

<!-- 界说car这个bean,id为myCar -->
<bean id="myCar" class="cn.tewuyiang.pojo.Car">
    <!-- 
        为car的属性注入值,由于speed和price都是基本数据类型,以是使用value为属性设置值;
        注重,这里的name为speed和price,不是由于属性名就是speed和price,
        而是set方式划分为setSpeed和setPrice,名称是通过将set删除,然后将第一个字母变小写得出;
    -->
    <property name="speed" value="100"/>
    <property name="price" value="99999.9"/>
</bean>

<!-- 界说user这个bean -->
<bean id="user" class="cn.tewuyiang.pojo.User">
    <property name="name" value="aaa" />
    <property name="age" value="123" />
    <!-- car是引用类型,以是这里使用ref为其注入值,注入的就是上面界说的myCar 
         基本数据类型或Java包装类型使用value,
         而引用类型使用ref,引用另外一个bean的id 
    -->
    <property name="car" ref="myCar" />
</bean>

  通过上面的设置,就可以为CarUser这两个类型的bean注入值了。需要注重的是,property的name属性,填写的不是属性的名称,而是set方式去除set,然后将第一个字符小写后的效果。对于基本数据类型,或者是Java的包装类型(好比String),使用value注入值,而对于引用类型,则使用ref,传入其他bean的id。接下来我们就可以测试效果了:

@Test
public void test1() {
    ApplicationContext context =
        new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    // 获取user这个bean
    User user = context.getBean(User.class);
    // 输生产看效果
    System.out.println(user);
}

  由于user包罗car的引用,以是我们直接输出user,也能够看到car的情形,输入效果如下:

User{name='aaa', age=123, car=Car{speed=100, price=99999.9}}

2.3 组织器注入

  下面我们来说第二种方式——组织器注入。听名字就可以知道,这种注入值的方式,就是通过挪用bean所属类的带参组织器为bean的属性注入值。这也就意味着,我们若是需要使用组织器注入,就得为类提供包罗参数的组织方式。组织器注入,现实上有多种匹配属性值的方式,下面我们就来一一列举。我们这里依然使用2.2中界说的CarUser这两个类,测试方式以及类的界说都不需要变,需要改变的仅仅是xml设置文件。

(一)匹配组织器的参数名称

  我们需要通过constructor-arg标签为组织器传入参数值,然则每个constructor-arg标签对应哪一个参数值呢?这就有多种方式指定了。第一种就是直接匹配参数名,设置如下:

<bean id="myCar" class="cn.tewuyiang.pojo.Car">
    <!-- 通过constructor-arg的name属性,指定组织器参数的名称,为参数赋值 -->
    <constructor-arg name="speed" value="100" />
    <constructor-arg name="price" value="99999.9"/>
</bean>

<bean id="user" class="cn.tewuyiang.pojo.User">
    <constructor-arg name="name" value="aaa" />
    <constructor-arg name="age" value="123" />
    <!-- 
         和之前一样,基本数据类型或Java包装类型使用value,
         而引用类型使用ref,引用另外一个bean的id 
    -->
    <constructor-arg name="car" ref="myCar" />
</bean>

  这样就完成了,测试代码和之前一样,运行效果也一样,我这里就不贴出来了。有人看完之后,可能会以为这里的设置和set注入时的设置险些一样,除了一个使用property,一个使用constructor-arg。确实,写法上一样,然则示意的寄义却完全差别。property的name属性,是通过set方式的名称得来;而constructor-arg的name,则是组织器参数的名称


(二)匹配组织器的参数下标

  上面是通过组织器参数的名称,匹配需要传入的值,那种方式最为直观,而Spring还提供另外两种方式匹配参数,这里就来说说通过参数在参数列表中的下标举行匹配的方式。下面的设置,请连系2.2节中UserCar的组织方式一起阅读,设置方式如下:

<bean id="car" class="cn.tewuyiang.pojo.Car">
    <!-- 下标编号从0最先,组织器的第一个参数是speed,为它赋值100 -->
    <constructor-arg index="0" value="100" />
    <!-- 组织器的第二个参数是price,为它赋值99999.9 -->
    <constructor-arg index="1" value="99999.9"/>
</bean>

<bean id="user" class="cn.tewuyiang.pojo.User">
    <!-- 与上面car的设置同理 -->
    <constructor-arg index="0" value="aaa" />
    <constructor-arg index="1" value="123" />
    <constructor-arg index="2" ref="car" />
</bean>

  上面就是通过参数的下标为组织器的参数赋值,需要注重的是,参实的下标从0最先。使用上面的方式设置,若赋值的类型与参数的类型不一致,将会在容器初始化bean的时刻抛出异常。若是bean存在多个参数数目一样的组织器,Spring容器会自动找到类型匹配的谁人举行挪用。好比说,Car有如下两个组织器,Spring容器将会挪用第二个,由于上面的设置中,index = 1对应的valuedouble类型,与第二个组织器匹配,而第一个不匹配:

public Car(double price, int speed) {
    this.speed = speed;
    this.price = price;
}
// 将使用匹配这个组织器
public Car(int speed, double price) {
    this.speed = speed;
    this.price = price;
}

  还存在另外一种特殊情形,那就是多个组织器都知足bean的设置,此时选择哪一个?假设当前car的设置是这样的:

<bean id="car" class="cn.tewuyiang.pojo.Car">
    <!-- 两个下标的value值都是整数 -->
    <constructor-arg index="0" value="100" />
    <constructor-arg index="1" value="999"/>
</bean>

  假设Car照样有上面两个组织器,两个组织器都是一个int类型一个double类型的参数,只是位置差别。而设置中,指定的两个值都是int类型。然则,int类型也可以使用double类型存储,以是上面两个组织器都是匹配的,此时挪用哪一个呢?结论就是挪用第二个。自己去实验就会发现,若存在多个组织器匹配bean的界说,Spring容器总是使用最后一个知足条件的组织器


(三)匹配组织器的参数类型

  下面说最后一种匹配方式——匹配组织器的参数类型。直接看设置文件吧:

<bean id="car" class="cn.tewuyiang.pojo.Car">
    <!-- 使用type属性匹配类型,car的组织器包罗两个参数,一个是int类型,一个是double类型 -->
    <constructor-arg type="int" value="100" />
    <constructor-arg type="double" value="99999.9"/>
</bean>

<bean id="user" class="cn.tewuyiang.pojo.User">
    <!-- 对于引用类型,需要使用限制类名 -->
    <constructor-arg type="java.lang.String" value="aaa" />
    <constructor-arg type="int" value="123" />
    <constructor-arg type="cn.tewuyiang.pojo.Car" ref="car" />
</bean>

  上面应该不难理解,直接通过匹配组织器的参数类型,从而选择一个能够完全匹配的组织器,挪用这个组织器完成bean的建立和属性注入。需要注重的是,上面的设置中,类型并不需要按组织器中声明的顺序编写,Spring也能举行匹配。这也就意味着可能泛起多个能够匹配的组织器,和上一个例子中一样。好比说,Car照样有下面两个组织器:

public Car(double price, int speed) {
    // 输出一句话,看是否挪用这个组织器
    System.out.println(111);
    this.speed = speed;
    this.price = price;
}
// 将使用匹配这个组织器
public Car(int speed, double price) {
    // 输出一句话,看是否挪用这个组织器
    System.out.println(222);
    this.speed = speed;
    this.price = price;
}

  上面两个组织器都是一个int,一个double类型的参数,都相符xml文件中,car这个bean的设置。通过测试发现,Spring容器使用的永远都是最后一个相符条件的组织器,这和上面通过下标匹配是一致的。需要说明的一点是,这三种使用组织器注入的方式,可以混用


2.4 静态工厂注入

  静态工厂注入就是我们编写一个静态的工厂方式,这个工厂方式会返回一个我们需要的值,然后在设置文件中,我们指定使用这个工厂方式建立bean。首先我们需要一个静态工厂,如下所示:

public class SimpleFactory {

    /**
     * 静态工厂,返回一个Car的实例工具
     */
    public static Car getCar() {
        return new Car(12345, 5.4321);
    }
}

  下面我们需要在xml中设置car这个bean,并指定它由工厂方式举行建立。设置如下:

<!-- 
	注重,这里的设置并不是建立一个SimpleFactory工具,取名为myCar,
    这一句设置的意思是,挪用SimpleFactory的getCar方式,建立一个car实例工具,
    将这个car工具取名为myCar。
-->
<bean id="car" class="cn.tewuyiang.factory.SimpleFactory" factory-method="getCar"/>

<bean id="user" class="cn.tewuyiang.pojo.User">
    <!-- name和age使用set注入 -->
    <property name="name" value="aaa"/>
    <property name="age" value="123"/>
    <!-- 将上面设置的car,注入到user的car属性中 -->
    <property name="car" ref="car"/>
</bean>

  以上就设置乐成了,测试方式以及执行效果如下,注重看car的属性值,就是我们在静态工厂中设置的那样,这说明,Spring容器确实是使用我们界说的静态工厂方式,建立了car这个bean

@Test
public void test1() {
    ApplicationContext context =
        new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    // 获取静态工厂建立的car
    Car car = (Car) context.getBean("car");
    // 获取user
    User user = context.getBean(User.class);
    System.out.println(car);
    System.out.println(user);
}

  输出如下所示:

Car{speed=12345, price=5.4321}
User{name='aaa', age=123, car=Car{speed=12345, price=5.4321}}

2.5 实例工厂注入

  实例工厂与静态工厂类似,差别的是,静态工厂挪用工厂方式不需要先建立工厂类的工具,由于静态方式可以直接通过类挪用,以是在上面的设置文件中,并没有声明工厂类的bean。然则,实例工厂,需要有一个实例工具,才气挪用它的工厂方式。我们先看看实例工厂的界说:

public class SimpleFactory {

    /**
     * 实例工厂方式,返回一个Car的实例工具
     */
    public Car getCar() {
        return new Car(12345, 5.4321);
    }

    /**
     * 实例工厂方式,返回一个String
     */
    public String getName() {
        return "tewuyiang";
    }

    /**
     * 实例工厂方式,返回一个int,在Spring容器中会被包装成Integer
     */
    public int getAge() {
        return 128;
    }
}

  在上面的工厂类中,共界说了三个工厂方式,划分用来返回user所需的carname以及age,而设置文件如下:

<!-- 声明实例工厂bean,Spring容器需要先建立一个SimpleFactory工具,才气挪用工厂方式 -->
<bean id="factory" class="cn.tewuyiang.factory.SimpleFactory" />

<!-- 
    通过实例工厂的工厂方式,建立三个bean,通过factory-bean指定工厂工具,
    通过factory-method指定需要挪用的工厂方式
-->
<bean id="name" factory-bean="factory" factory-method="getName" />
<bean id="age" factory-bean="factory" factory-method="getAge" />
<bean id="car" factory-bean="factory" factory-method="getCar" />

<bean id="user" class="cn.tewuyiang.pojo.User">
    <!-- 将上面通过实例工厂方式建立的bean,注入到user中 -->
    <property name="name" ref="name"/>
    <property name="age" ref="age"/>
    <property name="car" ref="car"/>
</bean>

  我们实验从Spring容器中取出nameagecar以及user,看看它们的值,测试代码如下:

@Test
public void test1() {
    ApplicationContext context =
        new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    // 获取静态工厂建立的car,name和age这三个bean
    Car car = (Car) context.getBean("car");
    String name = (String) context.getBean("name");
    Integer age = (Integer) context.getBean("age");
    // 获取user这个bean
    User user = context.getBean(User.class);
    System.out.println(car);
    System.out.println(name);
    System.out.println(age);
    System.out.println(user);
}

  以下就是输出效果,可以看到,我们通过工厂建立的bean,都在Spring容器中能够获取到:

Car{speed=12345, price=5.4321}
tewuyiang
128
User{name='tewuyiang', age=128, car=Car{speed=12345, price=5.4321}}

2.6 使用注解注入

  如果需要使用注解的方式为bean注入属性值,应该这么操作呢?首先,若是bean依赖于其他bean(好比User依赖Car),那么我们可以使用@Autowired或者@Resource这两个注解举行依赖注入,这个人人应该都知道。然则若是要为基本数据类型或者是Java的封装类型(好比String)赋值呢?这时刻可以使用@Value注解。这里我就不演示了,感兴趣的可以自行去研究,应该是比xml的方式简朴多了。


三、总结

  以上就对Spring基于xml设置文件举行属性注入的方式做了一个还算详细的先容。实在这一部门的内容照样对照基础,究竟只是Spring的使用,并不涉及原理,只要自己实验写一遍就了解了。若以上内容存在错误或不足,迎接指正,共同进步。也希望以上内容对需要的人有所辅助。


四、参考

  • https://blog.csdn.net/a745233700/article/detAIls/89307518

  • https://blog.csdn.net/mChenys/article/details/88894751

,

SuNBet

www.0379st.com信誉来自于每一位客户的口碑,Sunbet贴心的服务,让你尊享贵宾通道,秒速提现,秒速到账,同行业中体验最佳。

Sunbet网站内容转载自互联网,如有侵权,联系Sunbet删除。

本文链接地址:http://www.caac-feixingjia.com/post/815.html

相关文章

发表评论