Spring的三种创建方式和各种属性的注入(二)

简介: Spring的三种创建方式和各种属性的注入(二)

一. 创建的三种方式


spring 创建Bean时,有三种方式,常见的是用无参构造方法,利用反射进行构造。

普通的pojo 类 Person.java


package com.yjl.pojo;
/**
 @author:yuejl
 @date: 2019年4月15日 下午3:29:48
 @Description spring的一个简单的类
*/
public class Person {
  /**
   * @param name 名称
   * @param description 描述
   */
  private String name;
  private String description;
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getDescription() {
    return description;
  }
  public void setDescription(String description) {
    this.description = description;
  }
  public String say(){
    return this.name+":"+this.description;
  }
}


一.一 无参构造方法创建


<bean id="person" class="com.yjl.pojo.Person"></bean>


@Test
  public void test1(){
    ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
    Person person=(Person) applicationContext.getBean("person");
    person.setName("两个蝴蝶飞1");
    person.setDescription("一个充满希望的程序员1");
    System.out.println(person.say());
  }


其余两种的测试方式,与上面是一样的,只是将 bean()中的参数值改变。 不再重复写。


20190413161353678.png


一.二 类的静态方法创建


package com.yjl.factory;
import com.yjl.pojo.Person;
/**
 @author:yuejl
 @date: 2019年4月15日 下午4:45:35
 @Description 类的相关描述
*/
public class PersonFactory {
  // 使用类的静态方法
  public static Person getPerson2(){
    return new Person();
  }
}


<bean id="personFactory" class="com.yjl.factory.PersonFactory"
  factory-method="getPerson2"></bean>


一.三 类的普通方法创建


package com.yjl.factory;
import com.yjl.pojo.Person;
/**
 @author:yuejl
 @date: 2019年4月15日 下午4:45:35
 @Description 类的相关描述
*/
public class PersonFactory {
  // 普通的方法
  public Person getPerson3(){
    return new Person();
  }
}


<!--先创建工厂的实例化-->
<bean id="personFactory" class="com.yjl.factory.PersonFactory"></bean> -->
<!--利用factory-bean 和factory-method 来指定引用哪个实例,调用的哪个方法-->
<bean id="person" factory-bean="personFactory" factory-method="getPerson3"> </bean>


二. 类属性的注入方式


类属性的注入方式一般有三种,一,setter方法注入,二 构造方法注入,三 接口注入,但一般常见是setter方法和构造方式。 其中,接口注入类似于:


图片引用于黑马程序员视频的Spring 教程第一天。


20190415195833283.png


其中,所用的两个类 Car.java 和User.java 代码为:

Car.java


package com.yjl.pojo;
/**
 @author:yuejl
 @date: 2019年4月15日 下午4:54:57
 @Description 类的相关描述
*/
public class Car {
  /**
   * @param name 名称
   * @param description 描述
   */
  private String name;
  private String description;
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getDescription() {
    return description;
  }
  public void setDescription(String description) {
    this.description = description;
  }
  public Car() {
    super();
  }
  public Car(String name, String description) {
    super();
    this.name = name;
    this.description = description;
  }
  @Override
  public String toString() {
    return "Car [name=" + name + ", description=" + description + "]";
  }
}


User.java. User类中有一个Car的属性引用。


package com.yjl.pojo;
/**
 @author:yuejl
 @date: 2019年4月15日 下午4:54:51
 @Description 类的相关描述
*/
public class User {
  /**
   * @param name 名称
   * @param description 描述
   */
  private String name;
  private String description;
  // 注入对象属性,而不是普通的属性,可扩展为接口形式。
  private Car car;
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getDescription() {
    return description;
  }
  public void setDescription(String description) {
    this.description = description;
  }
  public Car getCar() {
    return car;
  }
  public void setCar(Car car) {
    this.car = car;
  }
  public User() {
    super();
  }
  public User(String name, String description) {
    super();
    this.name = name;
    this.description = description;
  }
  public User(String name, String description, Car car) {
    super();
    this.name = name;
    this.description = description;
    this.car = car;
  }
  @Override
  public String toString() {
    return "User [name=" + name + ", description=" + description + "]";
  }
}


二.一 Setter方式注入


  1. 注入普通的属性,用 property 的name 和value 属性,name指定属性名称,value 指明值。


<bean id="userSetter1" class="com.yjl.pojo.User">
    <property name="name" value="两个蝴蝶飞1"></property>
    <property name="description" value="一个充满希望的程序员1"></property>
    <!--注入空值-->
    <!--<property name="name" /><null/></property>-->
  </bean>


测试方法为:


@Test
  public void test1(){
    ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
    User user=applicationContext.getBean("userSetter1",User.class);
    System.out.println(user);
  }


2019041520050421.png


2. 注入对象属性引入,用 property 的name 和ref .


<!-- ref必须要引用的是对象类型 -->
  <bean id="userSetter2" class="com.yjl.pojo.User">
    <property name="name" value="两个蝴蝶飞1"></property>
    <property name="description" value="一个充满希望的程序员1"></property>
    <!--与com.yjl.pojo.Car 所对应的id值一样-->
    <property name="car" ref="carSetter"></property>
    <!--注入空值-->
    <!--<property name="car" /><null/></property>-->
  </bean>
  <bean id="carSetter" class="com.yjl.pojo.Car">
    <property name="name" value="牛车1"></property>
    <property name="description" value="一辆虽破却不丑的车1"></property>
  </bean>


测试方法为:


@Test
  public void test2(){
    ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
    User user=applicationContext.getBean("userSetter2",User.class);
    System.out.println(user);
    Car car=user.getCar();
    System.out.println(car);
  }


20190415200523208.png


下面的测试方法与上面的一样,只是改变bean的传入参数值,不再重复写。


二. 构造方法的注入


利用constructor-arg 进行注入。 可以用name和指明属性


  <bean id="userConstructor1" class="com.yjl.pojo.User">
    <constructor-arg name="name" value="两个蝴蝶飞2"></constructor-arg>
    <constructor-arg name="description" value="一个充满希望的程序员2"></constructor-arg>
  </bean>


也可以利用index 来指明索引,从0开始。


<!-- 是从0开始的。 如果写成从1开始,会报错。 -->
  <bean id="userConstructor2" class="com.yjl.pojo.User">
    <constructor-arg index="0" value="两个蝴蝶飞2" type="java.lang.String"></constructor-arg>
    <constructor-arg index="1" value="一个充满希望的程序员2"></constructor-arg>
  </bean>


当然,也可以引入对象属性,可以指明类型


<bean id="userConstructor3" class="com.yjl.pojo.User">
    <constructor-arg name="name" value="两个蝴蝶飞2" type="java.lang.String"></constructor-arg>
    <constructor-arg name="description" value="一个充满希望的程序员2"></constructor-arg>
    <!--type 为全限定名称-->
    <constructor-arg name="car" ref="carConstructor"  type="com.yjl.pojo.Car"></constructor-arg>
  </bean>
  <bean id="carConstructor" class="com.yjl.pojo.Car">
    <constructor-arg name="name" value="牛车2"></constructor-arg>
    <constructor-arg name="description" value="一辆虽破却不丑的车2"></constructor-arg>
  </bean>


二.三 P命名空间的注入


  1. 首先要引入P空间的约束


 xmlns:p="http://www.springframework.org/schema/p"


  1. 引入属性,注意 p:name是引入到 节点里面的,当做属性进行处理的。


<bean id="userP1" class="com.yjl.pojo.User" 
  p:name="两个蝴蝶飞3" p:description="一个充满希望的程序员3"></bean>


当然,也可以引入对象属性,用p:属性-ref


<bean id="userP2" class="com.yjl.pojo.User" 
  p:name="两个蝴蝶飞3" p:description="一个充满希望的程序员3" p:car-ref="carP1"></bean>
  <bean id="carP1" class="com.yjl.pojo.Car"
  p:name="牛车3" p:description="一辆虽破却不丑的车3">
  </bean>


二.四 SpEL方式注入


利用"#" 进行相应的注入


<bean id="userEL1" class="com.yjl.pojo.User">
    <property name="name" value="#{'两个蝴蝶飞4'}"></property>
    <property name="description" value="#{'一个充满希望的程序员4'}"></property>
  </bean>


也可以引入对象属性,


<bean id="userEL2" class="com.yjl.pojo.User">
    <property name="name" value="#{'两个蝴蝶飞4'}"></property>
    <property name="description" value="#{'一个充满希望的程序员4'}"></property>
    <property name="car" value="#{carEL1}"></property>
  </bean>
  <bean id="carEL1" class="com.yjl.pojo.Car">
    <property name="name" value="#{'牛车4'}"></property>
    <property name="description" value="#{'一辆虽破却不丑的车4'}"></property>
  </bean>


强大的一点,可以直接引入对象属性里面的属性值


<bean id="userEL3" class="com.yjl.pojo.User">
    <!--carEl1 属性里面的值 ,利用 "." 来取出。-->
    <property name="name" value="#{carEL1.name}"></property>
    <property name="description" value="#{carEL1.description}"></property>
    <property name="car" value="#{carEL1}"></property>
  </bean>
  <bean id="carEL1" class="com.yjl.pojo.Car">
    <property name="name" value="#{'牛车4'}"></property>
    <property name="description" value="#{'一辆虽破却不丑的车4'}"></property>
  </bean>


三. 注入复杂的数据类型


注入的复杂类型,可以为数组,集合List,集合Set,集合Map,属性 Properties, 其中集合可以放置的是常见的属性如基本属性和String字符串,也可以放置自定义的对象。


package com.yjl.pojo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
 @author:yuejl
 @date: 2019年4月15日 下午6:51:03
 @Description 类的相关描述
*/
public class Bean {
  private String [] arr;
  //private List<String> list; //建议最好是初始化
  private List<String> list=new ArrayList<String>(); 
  private Set<String> set=new HashSet<String>();
  private Map<String,String> map=new HashMap<String,String>();
  private Properties properties;
  private List<User> userList=new ArrayList<User>();
  public String[] getArr() {
    return arr;
  }
  public void setArr(String[] arr) {
    this.arr = arr;
  }
  public List<String> getList() {
    return list;
  }
  public void setList(List<String> list) {
    this.list = list;
  }
  public Set<String> getSet() {
    return set;
  }
  public void setSet(Set<String> set) {
    this.set = set;
  }
  public Map<String, String> getMap() {
    return map;
  }
  public void setMap(Map<String, String> map) {
    this.map = map;
  }
  public Properties getProperties() {
    return properties;
  }
  public void setProperties(Properties properties) {
    this.properties = properties;
  }
  public List<User> getUserList() {
    return userList;
  }
  public void setUserList(List<User> userList) {
    this.userList = userList;
  }
}


三.一 注入数组


 <bean id="bean1" class="com.yjl.pojo.Bean">
      <!-- 注入数组 -->
      <property name="arr">
        <array>
          <value>张三</value>
          <value>李四</value>
          <value>王二</value>
        </array>
      </property>
    </bean>


可以利用<array>,当然也可以利用常见的<list>


<bean id="bean2" class="com.yjl.pojo.Bean">
      <!-- 注入数组 -->
      <property name="arr">
        <list>
          <value>张三</value>
          <value>李四</value>
          <value>王二</value>
        </list>
      </property>
    </bean>


两种方式均可以。

测试方法为:


@Test
  public void test1(){
    ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
    Bean bean=applicationContext.getBean("bean1",Bean.class);
    //Bean bean=applicationContext.getBean("bean2",Bean.class);
    String [] arr=bean.getArr();
    for (String string : arr) {
      System.out.println("输出值为:"+string);
    }
  }


三.二 注入List集合


<bean id="bean3" class="com.yjl.pojo.Bean">
      <!-- 注入List -->
      <property name="list">
        <list>
          <value>张三</value>
          <value>李四</value>
          <value>王二</value>
          <!-- 注入自定义对象时-->
          <!-- <ref bean="user"/> -->
        </list>
      </property>
    </bean>


测试方法为:


@Test
  public void test3(){
    ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
    Bean bean=applicationContext.getBean("bean3",Bean.class);
    List<String> list=bean.getList();
    list.forEach(n ->System.out.println(n));
  }


三.三 注入Set


<bean id="bean4" class="com.yjl.pojo.Bean">
      <!-- 注入set -->
      <property name="set">
        <set>
          <value>张三</value>
          <value>李四</value>
          <value>王二</value>
          <!-- <ref bean="user"/> -->
        </set>
      </property>
    </bean>


测试方法为:


@Test
  public void test4(){
    ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
    Bean bean=applicationContext.getBean("bean4",Bean.class);
    Set<String> set=bean.getSet();
    set.forEach(n ->System.out.println(n));
  }


三.四 注入Map


<bean id="bean5" class="com.yjl.pojo.Bean">
      <!-- 注入map -->
      <property name="map">
        <map>
          <!-- 不可以这种写法 -->
          <!-- <entry>
            <key>张三</key>
            <value>不是好人</value>
          </entry> -->
          <!-- 可以这样 -->
          <entry key="张三" value="不是好人"> </entry>
          <entry key="李四" value="是好人"> </entry>
          <entry key="王二" value="不是好人"> </entry>
          <!-- <entry key="王二"  value-ref="user"> </entry> -->
        </map>
      </property>
    </bean>


测试方法为:


@Test
  public void test5(){
    ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
    Bean bean=applicationContext.getBean("bean5",Bean.class);
    Map<String,String> map=bean.getMap();
    for (Map.Entry<String,String> m:map.entrySet()) {
      System.out.println(m.getKey()+":"+m.getValue());
    }
  }


三.五 注入Properties


<bean id="bean6" class="com.yjl.pojo.Bean">
      <!-- 注入Properties -->
      <property name="properties">
        <props>
          <prop key="hello">你好</prop>
          <prop key="world">世界</prop>
        </props>
      </property>
    </bean>


测试方法为:


@Test
  public void test6(){
    ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
    Bean bean=applicationContext.getBean("bean6",Bean.class);
    Properties properties=bean.getProperties();
    System.out.println(properties.get("hello"));
    System.out.println(properties.get("world"));
  }


三.六 注入自定义对象


<bean id="bean7" class="com.yjl.pojo.Bean">
      <!-- 注入自定义对象 -->
      <property name="userList">
        <list>
          <!-- 注入集合时 -->
          <ref bean="user"/>
          <ref bean="user"/>
          <ref bean="user"/>
        </list>
      </property>
    </bean>
    <bean id="user" class="com.yjl.pojo.User">
    <property name="name" value="两个蝴蝶飞1"></property>
    <property name="description" value="一个充满希望的程序员1"></property>
  </bean>


测试方法为:


@Test
  public void test7(){
    ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
    Bean bean=applicationContext.getBean("bean7",Bean.class);
    List<User> list=bean.getUserList();
    list.forEach(n ->System.out.println(n));
  }


谢谢!!!


相关文章
|
9天前
|
Java Spring
在使用Spring的`@Value`注解注入属性值时,有一些特殊字符需要注意
【10月更文挑战第9天】在使用Spring的`@Value`注解注入属性值时,需注意一些特殊字符的正确处理方法,包括空格、引号、反斜杠、新行、制表符、逗号、大括号、$、百分号及其他特殊字符。通过适当包裹或转义,确保这些字符能被正确解析和注入。
|
21天前
|
Java 测试技术 程序员
为什么Spring不推荐@Autowired用于字段注入?
作为Java程序员,Spring框架在日常开发中使用频繁,其依赖注入机制带来了极大的便利。然而,尽管@Autowired注解简化了依赖注入,Spring官方却不推荐在字段上使用它。本文将探讨字段注入的现状及其存在的问题,如难以进行单元测试、违反单一职责原则及易引发NPE等,并介绍为何Spring推荐构造器注入,包括增强代码可读性和维护性、方便单元测试以及避免NPE等问题。通过示例代码展示如何将字段注入重构为构造器注入,提高代码质量。
|
3月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
4月前
|
Java 测试技术 数据库
Spring Boot中的项目属性配置
本节课主要讲解了 Spring Boot 中如何在业务代码中读取相关配置,包括单一配置和多个配置项,在微服务中,这种情况非常常见,往往会有很多其他微服务需要调用,所以封装一个配置类来接收这些配置是个很好的处理方式。除此之外,例如数据库相关的连接参数等等,也可以放到一个配置类中,其他遇到类似的场景,都可以这么处理。最后介绍了开发环境和生产环境配置的快速切换方式,省去了项目部署时,诸多配置信息的修改。
|
25天前
|
缓存 Java Spring
源码解读:Spring如何解决构造器注入的循环依赖?
本文详细探讨了Spring框架中的循环依赖问题,包括构造器注入和字段注入两种情况,并重点分析了构造器注入循环依赖的解决方案。文章通过具体示例展示了循环依赖的错误信息及常见场景,提出了三种解决方法:重构代码、使用字段依赖注入以及使用`@Lazy`注解。其中,`@Lazy`注解通过延迟初始化和动态代理机制有效解决了循环依赖问题。作者建议优先使用`@Lazy`注解,并提供了详细的源码解析和调试截图,帮助读者深入理解其实现机制。
19 1
|
5月前
|
XML druid Java
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
55 0
|
6月前
|
XML Java 程序员
Spring6框架中依赖注入的多种方式(推荐构造器注入)
依赖注入(DI)是一种过程,对象通过构造函数参数、工厂方法的参数或在对象实例构建后设置的属性来定义它们的依赖关系(即与其一起工作的其他对象)。
85 3
|
3月前
|
XML Java 数据格式
Spring5入门到实战------4、IOC容器-Bean管理XML方式、集合的注入(二)
这篇文章是Spring5框架的实战教程,主题是IOC容器中Bean的集合属性注入,通过XML配置方式。文章详细讲解了如何在Spring中注入数组、List、Map和Set类型的集合属性,并提供了相应的XML配置示例和Java类定义。此外,还介绍了如何在集合中注入对象类型值,以及如何使用Spring的util命名空间来实现集合的复用。最后,通过测试代码和结果展示了注入效果。
Spring5入门到实战------4、IOC容器-Bean管理XML方式、集合的注入(二)
|
3月前
|
Java Spring 开发者
Spring 框架配置属性绑定大比拼:@Value 与 @ConfigurationProperties,谁才是真正的王者?
【8月更文挑战第31天】Spring 框架提供 `@Value` 和 `@ConfigurationProperties` 两种配置属性绑定方式。`@Value` 简单直接,适用于简单场景,但处理复杂配置时略显不足。`@ConfigurationProperties` 则以类级别绑定配置,简化代码并更好组织配置信息。本文通过示例对比两者特点,帮助开发者根据具体需求选择合适的绑定方式,实现高效且易维护的配置管理。
49 0
|
3月前
|
缓存 Java 数据库连接
Spring Boot 资源文件属性配置,紧跟技术热点,为你的应用注入灵动活力!
【8月更文挑战第29天】在Spring Boot开发中,资源文件属性配置至关重要,它让开发者能灵活定制应用行为而不改动代码,极大提升了可维护性和扩展性。Spring Boot支持多种配置文件类型,如`application.properties`和`application.yml`,分别位于项目的resources目录下。`.properties`文件采用键值对形式,而`yml`文件则具有更清晰的层次结构,适合复杂配置。此外,Spring Boot还支持占位符引用和其他外部来源的属性值,便于不同环境下覆盖默认配置。通过合理配置,应用能快速适应各种环境与需求变化。
41 0