Spring 全家桶之 Spring Framework 5.3(三)
一、Bean生命周期
生命周期:即Bean从初始化到销毁的整个过程 在Tesla实体中增加两个方法,初始化方法和销毁方法
public class Tesla {
private String name;
private String battery; // 电池
private String engine; // 电机
private String chassis; //底盘
private String bodywork; // 车身
private String owner; // 车主
public void init(){
System.out.println(this.getClass().getName() + "init方法被调用");
}
public void destroy(){
System.out.println(this.getClass().getName() + "destroy方法被调用");
}
// 此处省略getter/setter/toString方法
}
在bean_life_cycle.xml中配置Tesla,初始化方法使用init-method属性表示,销毁方法使用destroy-method表示
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p = "http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.3.xsd">
<bean id="tesla" class="com.citi.entity.Tesla" init-method="init" destroy-method="destroy">
<property name="name" value="tesla"></property>
<property name="owner" value="musk"></property>
</bean>
</beans>
新增测试类BeanLifeCycleTest,增加测试方法
public class BeanLifeCycleTest {
@Test
public void testGetBean(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean_life_cycle.xml");
System.out.println("IoC容器创建完成");
Tesla tesla = context.getBean("tesla",Tesla.class);
System.out.println(tesla);
context.close();
}
}
控制台打印,初始化方法和销毁方法都被调用
修改xml中Bean的配置为多实例
<bean id="tesla" scope="prototype" class="com.citi.entity.Tesla" init-method="init" destroy-method="destroy">
<property name="name" value="tesla"></property>
<property name="owner" value="musk"></property>
</bean>
执行测试方法,控制台打印如下,多实例情况下只会调用初始化方法,不会调用销毁方法
- 多实例获取Bean的时候才会调用初始化方法,容器关闭不会调用destroy方法
- 单实例容器创建完成之前会调用初始化方法,Bean会在容器创建前创建,容器关闭时会调用Bean的destroy方法
Bean的后置处理器
BeanPostProcessor后置处理器接口可以定义Bean初始化前后执行的方法,新增config包,增加自定义的BeanPostProcessor
public class CustBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName + "初始化前调用该方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName + "初始化后调用该方法");
return bean;
}
}
在bean_life_cycle.xml增加CustBeanPostProcessor的xml配置,再增加一个 Person实体类的bean xml配置
<bean id="stark" class="com.citi.entity.Person">
<property name="lastName" value="stark"></property>
</bean>
<bean class="com.citi.config.CustBeanPostProcessor"></bean>
执行测试方法,每个Bean初始化前后都调用了后置处理器,后置处理器对容器中的每一个Bean都起作用
管理连接池及引用外部配置文件
以数据库连接池为例,数据库连接池最好是单例模式的,一个连接池中有多个数据库连接.
使用Spring Bean配置文件创建和管理数据库连接池
首先增加数据驱动及连接池的依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.14</version>
</dependency>
在connection_config.xml中增加数据库连接池的配置
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai&amp;allowPublicKeyRetrieval=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="initialSize" value="5"/>
<property name="maxActive" value="20"/>
</bean>
增加测试类
public class JdbcConnectionTest {
@Test
public void testGetBean() throws SQLException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:connection_config.xml");
System.out.println("IoC容器创建完成");
DruidDataSource dataSource = context.getBean("dataSource",DruidDataSource.class);
System.out.println(dataSource);
System.out.println(dataSource.getConnection());
}
}
数据库连接被成功创建
引用外部配置文件
在resources目录下创建数据库信息配置文件datasource.properties
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username=root
password=root
initialSize=5
maxActive=20
修改connect_config.xml中的配置,增加引用外部配置文件的配置,并修改连接池的配置
<!--引用外部配置文件-->
<context:property-placeholder location="classpath:database.properties"></context:property-placeholder>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}" />
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<property name="initialSize" value="${initialSize}"/>
<property name="maxActive" value="${maxActive}"/>
</bean>
执行测试方法,成功获取数据库连接
基于XML的自动装配
在之前章节中为各种属性正确赋值都是通过property标签进行手动赋值,使用bean标签中的autowire属性可以设置自动赋值,autowire配置的含义
- default:不自动装配,默认配置
- byName:以属性名作为ID进行赋值
- byType: 按照类型进行自动赋值,如果有多个相同类型的Bean在容器中会会报错
- constructor: 使用有参构造器进行赋值,先按照够再起的参数类型进行装配,如果容器中不存在car,直接赋值null,存在多个使用属性名作为区分
byName
在autowire.xml中增加配置
<bean id="car" class="com.citi.entity.Car">
<property name="carName" value="JAUGAR"></property>
<property name="color" value="英国绿"></property>
<property name="price" value="580000"></property>
</bean>
<bean id="stark" class="com.citi.entity.Person" autowire="byName">
<property name="lastName" value="stark"></property>
</bean>
Person实体类中有一个属性名为car,autowire使用byName配置可以自动将容器id为car的Bean自动赋值为Person
增加测试类AutowireBeanTest,测试方法testGetBean()
public class AutowireBeanTest {
@Test
public void testGetBean(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:autowire.xml");
System.out.println("IoC容器创建完成");
Person stark = context.getBean("stark",Person.class);
System.out.println(stark);
}
}
已成功将容器中的car自动装配的Person中的car,如果容器中不存在car,则无法自动赋值,Person bean中的car属性为null
byType
将xml配置中的byName改为byType,再次执行测试,可以将Person实体类中的Car属性及Map中的Car属性都自动装配上以及一些环境变量
如果容器中有多个Car,在xml中多配置一个Car Bean标签,执行测试
constructor
Person实体类中增加只包含Car的有参构造器
public Person(Car car) {
System.out.println("只包含Car的有参构造器被调用");
this.car = car;
}
autowire.xml中只保留一个car的xml配置,将person的xml配置中的autowire属性改为constructor,执行测试方法
如果存在多个car bean,增加一个car配置
<bean id="car01" class="com.citi.entity.Car">
<property name="carName" value="F-Type"></property>
<property name="color" value="英国绿"></property>
<property name="price" value="580000"></property>
</bean>
执行测试,成功赋值name为JAUGAR的car,当存在多个同类型的Bean时,优先按照属性名进行自动赋值
自动装配即自动赋值
Spring 表达式 (SpEL)
使用#{}表示Spring 表达式
- 支持使用字面量
- 支持引用其他Bean及Bean的属性
- 支持调用静态及非静态方法
- 支持所有的运算符 xml配置文件中修改Person xml配置
<bean id="stark" class="com.citi.entity.Person" autowire="constructor">
<property name="lastName" value="stark"></property>
<property name="age" value="#{1*3*4*5}"></property>
<property name="car" value="#{car}"></property>
<!--调用静态方法-->
<property name="email" value="#{T(java.util.UUID).randomUUID().toString().substring(0,5)}"></property>
<property name="gender" value="#{car.getCarName()}"></property>
</bean>
复制代码
执行测试方法,各属性使用EL表达式成功赋值
相关文章
- spring的事件监听应用场景_java监听器的原理与实现
- Spring 全家桶之 Spring Boot 2.6.4(七)- Exception
- Spring 全家桶之 Spring Data JPA(一)
- Spring 全家桶之 Spring Framework 5.3(二)- Part A
- Spring 全家桶之 Spring Framework 5.3(七)- 声明式事务
- Spring 全家桶之 Spring Framework 5.3(八)- Spring 整合 Java Web
- Spring 全家桶之 Spring Web MVC(三)- View & ViewResolve
- Spring 全家桶之 Spring Web MVC(五)- Data Binder
- spring注解有哪些_Spring 注解
- Spring Cloud实战|整合Gateway-网关还能这么整?
- Spring全家桶之SpringSession「建议收藏」
- Spring Webflux: Kotlin DSL [片断]
- 【开发日记】Spring中@Autowired和@Resource
- spring异常:No runnable methods 解决方法
- SpringBoot|Spring-Data-Redis 验证码短信存储服务
- Spring Cloud Gateway(微服务网关)
- 阿里技术文档:Redis+Nginx+Spring全家桶+Dubbo精选
- Java全能手册火了!Redis/Nginx/Dubbo/Spring全家桶/啥都有
- spring的启动过程——spring和springMVC父子容器的原理详解编程语言
- 开发者眼中的Spring与Java EE详解编程语言
- 运行 Spring Boot 应用的 3 种方式详解编程语言