Spring-注入参数详解-[字面值及引用其他Bean]

简介: Spring-注入参数详解-[字面值及引用其他Bean]

概述

在Spring配置文件中,不但可以将String、int等字面值注入bean中,还可以将集合、map等类型的数据注入Bean中, 此外还可以注入配置文件中其他定义的Bean.


字面值

所谓字面值一般指的是可以用字符串表示的值,这些值可以通过元素标签进行注入。

在默认情况下,基本数据类型及其封装类、String等类型都可以采用字面值注入的方式。

比如前几篇博文中经常使用的案例:

<bean id="plane" class="com.xgj.ioc.inject.set.Plane">
        <property name="brand">
            <value><![CDATA[Airbus&A380]]></value>
            <!-- 或者使用转义序列
            <value>Airbus&amp;A380</value>
            -->
        </property>
        <property name="color">
            <value>red</value>
        </property>
        <property name="speed">
            <value>700</value>
        </property>
    </bean>


XML中的特殊符号的处理

5个特殊符号

XML共有5个特殊符号 & < > " '

特殊符号的处理方式

  1. 添加特殊标签,阻止XML解析,让其当做普通的文本处理
  2. 使用XML转义序列处理这些特殊字符,如下
特殊符号 转移序列
< &lt;
> &gt;
& &amp;
&quot;
&apos;

关于注入值空格的处理

一般情况下,xml解析器会忽略元素标签内部字符串的前后空格,但是Spring不会忽略空格。

举个例子:

<property name="brand">
            <value>      Airbus&amp;A380       </value>
        </property>

运行结果如下:


引用其他Bean

Spring IoC容器中定义的Bean可以相互引用,IoC容器充当“红娘”的角色。

实例

警察类中有枪类型的属性

POJO类

package com.xgj.ioc.inject.construct.ref;
public class Police {
    private Gun gun;
    public void setGun(Gun gun) {
        this.gun = gun;
    }
    public void userGun() {
        gun.fire();
    }
}

POJO类

package com.xgj.ioc.inject.construct.ref;
public class Gun {
    public void fire() {
        System.out.println("Gun Fires");
    }
}

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="police" class="com.xgj.ioc.inject.construct.ref.Police">
        <property name="gun">
            <!-- 通过ref应用容器中的gun ,建立police和gun的依赖关系 -->
            <ref bean="gun" />
        </property>
    </bean>
    <bean id="gun" class="com.xgj.ioc.inject.construct.ref.Gun" />
</beans>

测试类

package com.xgj.ioc.inject.construct.ref;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class RefTest  {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com/xgj/ioc/inject/construct/ref/police-gun.xml");
        Police police = ctx.getBean("police", Police.class);
        police.userGun();
    }
}

运行结果


ref元素的3个属性

  1. bean:通过该属性可以应用同一容器或者父容器中的bean,这是最常见的形式
  2. local:通过该属性只能引用同一个配置文件中定义的Bean,它可以利用XML解析器自动检查引用的合法性,以便开发人员在编写配置文件时及时发现错误
  3. parent:引用父容器中的Bean,如的配置说明gun的Bean是父容器中的Bean

引用父容器中的Bean实例

演示子容器对父容器Bean的引用。

其中 beans_father.xml被父容器加载,beans_son.xml被子容器加载。

POJO类

package com.xgj.ioc.inject.construct.refParentBean;
public class Gun {
    private String brand;
    private int bulletNum;
    private double price;
    public void setBrand(String brand) {
        this.brand = brand;
    }
    public void setBulletNum(int bulletNum) {
        this.bulletNum = bulletNum;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public void gunInfo() {
        System.out.println("Gun Information brand:" + brand + ",bulletNum:"
                + bulletNum + ",price:" + price);
    }
}

POJO类

package com.xgj.ioc.inject.construct.refParentBean;
public class Police {
    private Gun gun;
    public void setGun(Gun gun) {
        this.gun = gun;
    }
    public void introduceGun() {
        gun.gunInfo();
    }
}

beans_father.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="gun" class="com.xgj.ioc.inject.construct.refParentBean.Gun">
        <property name="brand" value="父容器--伯莱塔92F" />
        <property name="bulletNum" value="11" />
        <property name="price" value="2888" />
    </bean>
</beans>

beans_son.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="gun" class="com.xgj.ioc.inject.construct.refParentBean.Gun">
        <property name="brand" value="柯尔特M2000" />
        <property name="bulletNum" value="7" />
        <property name="price" value="999" />
    </bean>
    <bean id="police" class="com.xgj.ioc.inject.construct.refParentBean.Police">
        <property name="gun">
            <!-- 通过parent属性,引用父容器中的gun,如果定义为bean="gun"则引用本容器中的gun -->
            <ref parent="gun"/>
        </property>
    </bean>
</beans>

测试类

package com.xgj.ioc.inject.construct.refParentBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class RefParentBeanTest {
    public static void main(String[] args) {
        // 父容器
        ApplicationContext pFather = new ClassPathXmlApplicationContext(
                "classpath:com/xgj/ioc/inject/construct/refParentBean/beans_father.xml");
        // 指定pFather为该容器的父容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                new String[] { "com/xgj/ioc/inject/construct/refParentBean/beans_son.xml" },
                pFather);
        Police police = ctx.getBean("police", Police.class);
        // 观察是否输出为父容器设置的属性
        police.introduceGun();
    }
}

运行结果


内部Bean

如果某个bean只会被其中一个引用,而不会被容器中的其它Bean引用,可以以内部Bean的方式注入。

内部bean和Java匿名内部类相似,既没有名字,也不会被前台bean引用,只能在声明处为外部Bean提供实例注入。

内部Bean即使提供了id、name、scope等属性,也会被忽略,scope默认prototype类型

举例:

其他类同上,区别仅在于beans的配置文件。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="police" class="com.xgj.ioc.inject.construct.innerBean.Police">
        <property name="gun">
            <!-- 如果gun bean只会被police引用,而不会被容器中的其它Bean引用,可以以内部Bean的方式注入 -->
            <bean class="com.xgj.ioc.inject.construct.innerBean.Gun">
                <property name="brand" value="柯尔特M2000"/>
                <property name="bulletNum" value="7"/>
                <property name="price" value="788"/>
            </bean>
        </property>
    </bean>
</beans>

运行结果


null值

如果希望往一个属性中注入一个null值? 使用专用的元素标签

POJO类

package com.xgj.ioc.inject.construct.nullValue;
public class Pilot {
    private Plane plane;
    public void setPlane(Plane plane) {
        this.plane = plane;
    }
    public void drivePlane() {
        System.out.println("Pilot is driving plane....");
        plane.info();
    }
}

POJO类

package com.xgj.ioc.inject.construct.nullValue;
public class Plane {
    private String brand;
    public void setBrand(String brand) {
        this.brand = brand;
    }
    public void info() {
        System.out.println("Plane brand:" + brand);
    }
}

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="plane" class="com.xgj.ioc.inject.construct.nullValue.Plane">
        <!-- 设置brand为 null -->
        <property name="brand" value="null" />
        <!-- 或者 <property name="brand"> <null/> </property> -->
        <!-- 错误的写法,这是spring会将 <value></value>解析为一个空字符串
        <property name="brand">
            <value></value>
        </property>-->
    </bean>
    <bean id="pilot" class="com.xgj.ioc.inject.construct.nullValue.Pilot">
        <property name="plane">
            <ref bean="plane" />
        </property>
    </bean>
</beans>

测试类

package com.xgj.ioc.inject.construct.nullValue;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class NullValueTest {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "classpath:com/xgj/ioc/inject/construct/nullValue/beans.xml");
        Pilot pilot = ctx.getBean("pilot", Pilot.class);
        pilot.drivePlane();
    }
}

运行结果:


级联属性

Spring支持级联属性的配置,假设我们希望在定义Pilot时,直接为Plane的属性提供注入值,可以采取如下方式:

<bean id="pilot" class="com.xgj.ioc.inject.construct.cascadeProperty.Pilot">
        <!-- 以圆点的方式定义级别属性 -->
        <property name="plane.brand" value="A380"/>
    </bean>

上述配置的含义:Spring将调用Pilot.getPlane().setBrand(“A380”)方法进行属性的注入操作。

此时,必须对Pilot的类进行改造,为Plane属性声明一个初始化对象。

实例:

POJO类

package com.xgj.ioc.inject.construct.cascadeProperty;
public class Pilot {
    // 声明初始化对象
    private Plane plane = new Plane();
    // 获取实例
    public Plane getPlane() {
        return plane;
    }
    public void setPlane(Plane plane) {
        this.plane = plane;
    }
    public void introduce() {
        plane.info();
    }
}

POJO类

package com.xgj.ioc.inject.construct.cascadeProperty;
public class Plane {
    private String brand;
    public void setBrand(String brand) {
        this.brand = brand;
    }
    public void info() {
        System.out.println("【Plane brand:】" + brand);
    }
}

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="pilot" class="com.xgj.ioc.inject.construct.cascadeProperty.Pilot">
        <!-- 以圆点的方式定义级别属性 -->
        <property name="plane.brand" value="A380"/>
    </bean>
</beans>

测试类

package com.xgj.ioc.inject.construct.cascadeProperty;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class CascadePropertyTest {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "classpath:com/xgj/ioc/inject/construct/cascadeProperty/beans.xml");
        Pilot pilot = ctx.getBean("pilot", Pilot.class);
        pilot.introduce();
    }
}

运行结果

如果没有未Plane属性提供Plan对象,Spring在设置级联属性时将抛出NullValueInNestedPathException异常。

我们在Plane类中 ,不对Plane进行new实例化操作,仅仅声明,再次运行NullValueInNestedPathException异常。

Caused by: org.springframework.beans.NullValueInNestedPathException: Invalid property 'plane' of bean class [com.xgj.ioc.inject.construct.cascadeProperty.Pilot]: Value of nested property 'plane' is null• 1

Spring对级联属性的层级没有限制。

相关文章
|
1月前
|
Java Spring
在使用Spring的`@Value`注解注入属性值时,有一些特殊字符需要注意
【10月更文挑战第9天】在使用Spring的`@Value`注解注入属性值时,需注意一些特殊字符的正确处理方法,包括空格、引号、反斜杠、新行、制表符、逗号、大括号、$、百分号及其他特殊字符。通过适当包裹或转义,确保这些字符能被正确解析和注入。
|
1月前
|
Java 测试技术 程序员
为什么Spring不推荐@Autowired用于字段注入?
作为Java程序员,Spring框架在日常开发中使用频繁,其依赖注入机制带来了极大的便利。然而,尽管@Autowired注解简化了依赖注入,Spring官方却不推荐在字段上使用它。本文将探讨字段注入的现状及其存在的问题,如难以进行单元测试、违反单一职责原则及易引发NPE等,并介绍为何Spring推荐构造器注入,包括增强代码可读性和维护性、方便单元测试以及避免NPE等问题。通过示例代码展示如何将字段注入重构为构造器注入,提高代码质量。
|
17天前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
1月前
|
JSON 前端开发 Java
Spring MVC——获取参数和响应
本文介绍了如何在Spring框架中通过不同的注解和方法获取URL参数、上传文件、处理cookie和session、以及响应不同类型的数据。具体内容包括使用`@PathVariable`获取URL中的参数,使用`MultipartFile`上传文件,通过`HttpServletRequest`和`@CookieValue`获取cookie,通过`HttpSession`和`@SessionAttribute`获取session,以及如何返回静态页面、HTML代码片段、JSON数据,并设置HTTP状态码和响应头。
51 1
Spring MVC——获取参数和响应
|
1月前
|
XML Java 数据格式
Spring从入门到入土(bean的一些子标签及注解的使用)
本文详细介绍了Spring框架中Bean的创建和使用,包括使用XML配置文件中的标签和注解来创建和管理Bean,以及如何通过构造器、Setter方法和属性注入来配置Bean。
72 9
Spring从入门到入土(bean的一些子标签及注解的使用)
|
1月前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
1月前
|
Java 开发者 Spring
Spring bean的生命周期详解!
本文详细解析Spring Bean的生命周期及其核心概念,并深入源码分析。Spring Bean是Spring框架的核心,由容器管理其生命周期。从实例化到销毁,共经历十个阶段,包括属性赋值、接口回调、初始化及销毁等。通过剖析`BeanFactory`、`ApplicationContext`等关键接口与类,帮助你深入了解Spring Bean的管理机制。希望本文能助你更好地掌握Spring Bean生命周期。
87 1
|
1月前
|
Java Spring
获取spring工厂中bean对象的两种方式
获取spring工厂中bean对象的两种方式
45 1
|
Java Spring 前端开发
spring 3.2 自定义参数绑定--日期格式转换器
springmvc配置文件 &lt;!-- 代替org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping 和org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter --&gt;
2440 0
|
2月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
下一篇
无影云桌面