持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第16天,点击查看活动详情
p命名空间
配置
<bean id="studentSix" class="com.sentiment.pojo.Student"
p:sid="111" p:sname="Sentiment" p:teacherMap-ref="studentMap"></bean>
测试
public void testByPnamesapce(){
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
Student studentSix = ioc.getBean("studentSix", Student.class);
System.out.println(studentSix);
}
spring管理数据源和引入外部属性文件
依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.31</version>
</dependency>
配置文件
jdbc.properties用的是mybatis里的
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--引入jdbc.properties配置文件-->
<context:property-placeholder location="jdbc.properties"></context:property-placeholder>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
</beans>
测试
@Test
public void dataSourceTest() throws SQLException {
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-datasource.xml");
DruidDataSource bean = ioc.getBean(DruidDataSource.class);
System.out.println(bean.getConnection());
}
bean的作用域及生命周期
作用域
在spring中可以通过配置bean标签的scope属性来指定bean的作用域范围,属性如下
常规情况下同一个ioc容器获取的bean值是相等的,在比较时会返回true
public void ScopeTest(){
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-scope.xml");
Student bean1 = ioc.getBean(Student.class);
Student bean2 = ioc.getBean(Student.class);
System.out.println(bean1 == bean2);
}
当设置了scope标签并且值为prototype时(默认为singleton),两个bean值则会不同,返回false
<bean id="student" class="com.sentiment.pojo.Student" scope="prototype">
<property name="sid" value="1842"></property>
<property name="sname" value="Sentiment"></property>
</bean>
如果是在WebApplicationContext环境下会有另外两个作用域
| 取值 | 含义 |
|---|---|
| request | 在一个请求范围内有效 |
| session | 在一个会话范围内有效 |
作用域注解: @Scope(value="singleton")
注意: 该注解可以用在@Bean标识的方法中,也可以标识在@Component标识的类中;从而表明获取到的对象为单例或多例模式
生命周期
生命周期过程
- 实例化
- 依赖注入(给对象设置属性)
- bean对象初始化之前的操作(由bean的后置处理器负责)
- 初始化:通过bean的init-method属性指定初始化方法
- bean对象初始化后的操作(由bean的后置处理器负责)
- bean对象的使用
- 销毁:通过bean的destroy-method属性来指定销毁的方法
- IOC容器的关闭
第一步是实例化,是由于ioc容器管理对象时,是通过工厂和反射获取的,所以会默认使用无参构造。
创建一个User类
public class User {
private Integer id;
private String username;
private String password;
private Integer age;
public User() {
System.out.println("生命周期1:实例化");
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setAge(Integer age) {
this.age = age;
}
public void setId(Integer id) {
System.out.println("生命周期2:依赖注入");
this.id = id;
}
void init(){
System.out.println("生命周期3:初始化");
}
void destroy(){
System.out.println("生命周期4:销毁");
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + ''' +
", password='" + password + ''' +
", age=" + age +
'}';
}
}
初始化和销毁需要在配置文件中定义
<!--init-method表示bean初始化方法,destory-meethod表示销毁方法-->
<bean id="student" class="com.sentiment.pojo.Student" scope="prototype">
<property name="sid" value="1842"></property>
<property name="sname" value="Sentiment"></property>
</bean>
测试
public void test(){
ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
User bean = ioc.getBean(User.class);
System.out.println(bean);
ioc.close();
}
最后的销毁部分是通过ioc.close()来完成的,而这里的用的是ConfigurableApplicationContext类型,因为ApplicationContext中没有close方法,而ConfigurableApplicationContext是他的子接口其中定义了刷新和关闭的方法。这里用原来的ClassPathXmlApplicationContext也是可以的
作用域对生命周期的影响
其实当执行第一步的时候就已经,初始化了,而这里的初始化只指单例模式的
如果换成多例模式即:配置中加上scope="prototype"后
此时运行便没有任何结果,而它的初始化则是在获取bean的时候生成
bean的后置处理器
在bean的声明周期过程中,初始化前后还有两个操作但是在上边并没有体现到
bean对象初始化之前的操作(由bean的后置处理器postProcessBeforeInitialization负责)
bean对象初始化后的操作(由bean的后置处理器postProcessAfterInitialization负责)
bean的后置处理器会在声明周期的初始化前后添加额外的操作,需要实现BeanPostProcessor接口,且配置到IOC容器中,需要注意的是,bean后置处理器不是单独针对某一个bean生效,而是针对IOC容器中所有bean都会执行
创建bean的后置处理器:
package com.sentiment.process;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化之前执行——>postProcessBeforeInitialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化之后执行——>postProcessAfterInitialization");
return bean; }
}
配置到IOC容器中
<bean id="mybeanprocessor" class="com.sentiment.process.MyBeanProcessor"></bean>
此时在执行则会调用bean的后置处理器