【Java从零到架构师第③季】【13】Spring-scope_Converter_引入其他配置文件_SpEL表达式

本文详细介绍了Spring中如何引入其他配置文件、使用PropertySourcesPlaceholderConfigurer、SpEL表达式以及bean的作用域。此外,还讲解了内置和自定义的Converter,包括日期格式转换的实现与优化。内容涵盖了Spring配置的核心知识点,适合Java开发者学习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


持续学习&持续更新中…

守破离


一、引入其他配置文件

在这里插入图片描述

在这里插入图片描述

注意

  1. ${username}是Spring的保留字,如果有在applicationContext.xml中引入了properties文件的话,会获取到当前电脑的用户名;如果没有引入properties文件的话,会获取到${username}这个字符串本身,不能使用
  2. classpath: 可省略,默认就是去classpath中去找

在这里插入图片描述

代码

db.properties:

jdbc.url=jdbc:mysql://localhost:3306/bookstore
jdbc.username=root
jdbc.password=root

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="db.properties"/>
                                         <!-- classpath: 可省略,默认就是去classpath中去找-->
<!--  <context:property-placeholder location="classpath:db.properties"/> -->
    <bean id="connection" class="programmer.lp.obj.ConnectionFactoryBean">
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

</beans>

二、PropertySourcesPlaceholderConfigurer

在这里插入图片描述

property-placeholder

<context:property-placeholder location="db.properties"/>

@PropertySource

@Configuration
@PropertySource("db.properties")
public class MainConfiguration {
	// ...
}

PropertySourcesPlaceholderConfigurer

<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
    <property name="location" value="db.properties"/>
</bean>

万变不离其宗:将bean放入IoC容器中即可:

@Configuration
public class MainConfiguration {

    // @Bean必须配合@Configuration使用
    @Bean
    public PropertySourcesPlaceholderConfigurer configurer() {
        PropertySourcesPlaceholderConfigurer configurer =
                new PropertySourcesPlaceholderConfigurer();
        configurer.setLocation(new ClassPathResource("db.properties"));
        return configurer;
    }

}

使用

@Component
public class Dog {
    private String name;
    @Value("${dev.username}")
    public void setName(String name) {
        this.name = name;
    }
	// ...
}

三、SpEL表达式

https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions

在这里插入图片描述

public class Food {
    public String getTestName() {
        return "小红苹果";
    }
}
public class Human {
    private String name;
    private String favoriteFood;
    private Date birthday;
    private Food food;
    private Integer fnByteLength;

    public Human() {
    }
    // getter setter
}
    <bean id="apple" class="programmer.lp.domain.Food"/>

    <bean id="baby" class="programmer.lp.domain.Human">
        <property name="name" value="小宝"/>
        <property name="food" value="#{apple}"/>
        <property name="favoriteFood" value="#{apple.testName}"/>
        <!-- <property name="favoriteFood" value="#{apple.getTestName()}"/> -->
        <property name="fnByteLength" value="#{apple.testName.bytes.length}"/>
        <!-- <property name="foodNameLength" value="#{apple.getTestName().getBytes().length}"/> -->
        <property name="birthday" value="#{new java.util.Date()}"/>
    </bean>

四、scope

https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-scopes

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码

<?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="person" class="programmer.lp.domain.Person" lazy-init="true" /> -->
    <bean id="person" class="programmer.lp.domain.Person" scope="prototype" />

</beans>

注意

  • scope的默认值为singleton。

  • singleton的含义:通过同一个id,在同一个IoC容器中,永远只能获取到同一个实例(但并没有使用单例设计模式。单例设计模式:一个类在整个程序运行过程中只有1个实例)

  • 当scope为singleton时,Spring在创建IoC容器时就会将其创建好并放入IoC容器,如果想要延迟其创建时机至初次调用时,可以使用lazy-init="true"

  • 当scope为prototype时,每次调用getBean时就会创建一个新的实例

  • 也就是说,lazy-init="true"对于scope="prototype"是没有意义的,lazy-init="true"是搭配scope="singleton"使用的。

五、Converter

1、内置的基本转换类型

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       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="person" class="programmer.lp.domain.Person" p:age="10" p:birthday="2000/07/20">
        <constructor-arg value="lpruoyu"/>
    </bean>
</beans>
2、自定义Converter

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

注意

  • Spring会通过conversionService这个id从IoC容器中获取一个ConversionService对象,通过ConversionService对象去转换类型。所以id必须固定为conversionService,不能使用其它的。
  • 当bean的scope为singleton(默认)时,在同一个IoC容器中,使用同一个id获取到的永远会是同一个实例,所以自己注册的日期转换器会将Spring的日期转换器覆盖掉,因此如果项目中要用到yyyy/MM/dd这种格式的日期,就需要自己将yyyy/MM/dd这种格式的日期添加至converters标签

代码

DateConverter:

public class DateConverter implements Converter<String, Date> {
    private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
    @Override
    public Date convert(String s) {
        try {
            return SIMPLE_DATE_FORMAT.parse(s);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

注册使用DateConverter:

方式一:

    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="programmer.lp.converter.DateConverter"/>
            </set>
        </property>
    </bean>
    <bean id="person" class="programmer.lp.domain.Person" p:birthday="2332-03-20">
        <constructor-arg value="lpruoyu"/>
        <property name="age" value="121"/>
    </bean>

方式二:

    <bean id="dateConverter" class="programmer.lp.converter.DateConverter"/>
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <ref bean="dateConverter"/>
            </set>
        </property>
    </bean>
    <bean id="person" class="programmer.lp.domain.Person" p:birthday="2222-08-08">
        <constructor-arg value="lpruoyu"/>
        <property name="age" value="121"/>
    </bean>

改进1

上面的方式还是不够好,因为我们之所以使用IoC容器,让Spring去管理这些bean就是为了解耦和减少依赖,但是上面还是在类中把日期格式写死了。因此可以考虑做出以下改进:

DateConverter:

public class DateConverter implements Converter<String, Date> {
    private String format;
    public void setFormat(String format) {
        this.format = format;
    }
    @Override
    public Date convert(String dateStr) {
        try {
            return new SimpleDateFormat(format).parse(dateStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

注册使用DateConverter:

    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="programmer.lp.converter.DateConverter" p:format="yyyy-MM-dd"/>
                <bean class="programmer.lp.converter.DateConverter">
                    <property name="format" value="yyyy年MM月dd日"/>
                </bean>
            </set>
        </property>
    </bean>
    <bean id="person" class="programmer.lp.domain.Person"
          p:age="121"
          p:birthday="2888年3月2日">
        <constructor-arg value="lpruoyu"/>
    </bean>

改进2

还可以考虑这样设计:

DateConverter:

public class DateConverter implements Converter<String, Date> {
    private Set<String> formats;
    public void setFormats(Set<String> formats) {
        this.formats = formats;
    }
    @Override
    public Date convert(String dateStr) {
        if (null == formats || formats.isEmpty()) return null;
        for (String format : formats) {
            try {
                return new SimpleDateFormat(format).parse(dateStr);
            } catch (Exception e) {
                System.out.println("不支持:<" + format + ">格式!");
            }
        }
        return null;
    }
}

注册使用DateConverter:

    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="programmer.lp.converter.DateConverter">
                    <property name="formats">
                        <set>
                            <value>yyyy/MM/dd</value>
                            <value>yyyy-MM-dd</value>
                            <value>yyyy_MM_dd</value>
                            <value>yyyy年MM月dd日</value>
                        </set>
                    </property>
                </bean>
            </set>
        </property>
    </bean>
    <bean id="person1" class="programmer.lp.domain.Person" p:birthday="2000-12-11"/>
    <bean id="person2" class="programmer.lp.domain.Person" p:birthday="2001_7_3"/>
    <bean id="person3" class="programmer.lp.domain.Person" p:birthday="1111年11月11日"/>

参考

小码哥-李明杰: Java从0到架构师③进阶互联网架构师.


本文完,感谢您的关注支持!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值