<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>6.0.6version>
dependency>
<dependency>
<groupId>org.junit.jupitergroupId>
<artifactId>junit-jupiter-apiartifactId>
<version>5.3.1version>
dependency>
dependencies>
- bean标签:通过配置bean标签告诉IOC容器需要创建对象的组件信息
- id属性:bean的唯一标识,方便后期获取Bean!
- class属性:组件类的全限定符!
- 注意:要求当前组件类必须包含无参数构造函数!
factory-method: 指定静态工厂方法,注意,该方法必须是static方法。
<bean id="notStaticMethod" class="com.doug.ClientService">bean>
<bean id="clientService" factory-bean="notStaticMethod" factory-method="createInstance">bean>
- constructor-arg标签:指定构造参数和对应的值
- constructor-arg标签:name属性指定参数名、index属性指定参数角标、value属性指定普通属性值
读取配置文件,实例化Bean对象
// 方法一:
//参数:String...locations 传入一个或者多个配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-bean-01.xml","spring-bean-02.xml");
//方法二:
// 先实例化,再指定配置文件,最后刷新容器触发Bean实例化
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
//设置配置配置文件,方法参数为可变参数,可以设置一个或者多个配置
context.setConfigLocations("spring-bean-01.xml","spring-bean-02.xml");
//后配置的文件,需要调用refresh方法,触发刷新配置
context.refresh();
//方式1: 根据id获取
//没有指定类型,返回为Object,需要类型转化!
HappyComponent happyComponent =
(HappyComponent) applicationContext.getBean("bean的id标识");
//使用组件对象
happyComponent.doWork();
//方式2: 根据类型获取
//根据类型获取,但是要求,同类型(当前类,或者之类,或者接口的实现类)只能有一个对象交给IoC容器管理
//配置两个或者以上出现: org.springframework.beans.factory.NoUniqueBeanDefinitionException 问题
HappyComponent happyComponent = applicationContext.getBean(HappyComponent.class);
happyComponent.doWork();
//方式3: 根据id和类型获取 !
// getBean("bean的id标识",class)
HelloComponent helloComponent = applicationContext.getBean("helloComponent", HelloComponent.class);
helloComponent.doWork();
bean
时,在满足bean唯一性的前提下,其实只是看:
对象 instanceof 指定的类型
』的返回结果,interfaceA happyComponent = applicationContext.getBean(interfaceA.class);
happyComponent.doWork();
IoC容器实例化和销毁组件对象
周期方法声明
周期方法配置bean
<bean id="beanPeriod" class="com.doug.BeanPeriod" init-method="Init" destroy-method="destroy"/>
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-bean-01.xml");
// 正常关闭 , 没调用这个方法,就只执行初始化,然后直接寄(非正常死亡)
applicationContext.close();
默认就是单例模式,
多例模式:组件对象 getBean 一次就会创建一个组件对象
- BeanFactory IoC容器最大的接口 IoC容器
- FactoryBean 标准化组件工厂的接口 组件
FactoryBean用于配置复杂的Bean对象,可以将创建过程存储在
FactoryBean
的getObject方法!
FactoryBean
接口提供三种方法:
T getObject()
:
返回此工厂创建的对象的实例。该返回值会被存储到IoC容器!
boolean isSingleton()
:
如果此 FactoryBean
返回单例,则返回 true
,否则返回 false
。此方法的默认实现返回 true
(注意,lombok插件使用,可能影响效果)。
Class> getObjectType()
: 返回 getObject()
方法返回的对象类型,如果事先不知道类型,则返回 null
。
FactoryBean使用场景:
- 代理类的创建
- 第三方框架整合
- 复杂对象实例化等
<bean id="javaBean" class="com.doug.ioc02.JavaBeanFactoryBean">
<property name="value" value="道格维克"/>
bean>
FactoryBean
- 是 Spring 中一种特殊的 bean,可以在 getObject() 工厂方法自定义的逻辑创建Bean!
- 是一种能够生产其他 Bean 的 Bean
- FactoryBean 在容器启动时被创建,而在实际使用时则是通过调用 getObject() 方法来得到其所生产的 Bean
- FactoryBean 可以自定义任何所需的初始化逻辑,生产出一些定制化的 bean
- 一般情况下,整合第三方框架,都是通过定义FactoryBean实现
BeanFactory
- Spring 框架的基础,其作为一个顶级接口定义了容器的基本行为
- 例如管理 bean 的生命周期、配置文件的加载和解析、bean 的装配和依赖注入等
- BeanFactory 接口提供了访问 bean 的方式
总的来说 , FactoryBean 和 BeanFactory 的区别 :
- 主要在于FactoryBean 是用于创建 bean 的接口,它提供了更加灵活的初始化定制功能,
- 而 BeanFactory是用于管理 bean 的框架基础接口,提供了基本的容器功能和 bean 生命周期管理。
搭建一个三层架构案例,模拟查询全部学生(学生表)信息,持久层使用JdbcTemplate和Druid技术,使用XML方式进行组件管理!
create database studb;
use studb;
CREATE TABLE students (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
gender VARCHAR(10) NOT NULL,
age INT,
class VARCHAR(50)
);
INSERT INTO students (id, name, gender, age, class)
VALUES
(1, '张三', '男', 20, '高中一班'),
(2, '李四', '男', 19, '高中二班'),
(3, '王五', '女', 18, '高中一班'),
(4, '赵六', '女', 20, '高中三班'),
(5, '刘七', '男', 19, '高中二班'),
(6, '陈八', '女', 18, '高中一班'),
(7, '杨九', '男', 20, '高中三班'),
(8, '吴十', '男', 19, '高中二班');
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>6.0.6version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.25version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.2.8version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>6.0.6version>
dependency>
dependencies>
package com.doug.ioc;
public class Student {
private Integer id;
private String name;
private String gender;
private Integer age;
private String classes;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getClasses() {
return classes;
}
public void setClasses(String classes) {
this.classes = classes;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", gender='" + gender + '\'' +
", age=" + age +
", classes='" + classes + '\'' +
'}';
}
}
从JAVA写法 改成 bean创建对象
@Test
public void testForIoC(){
// 1. 创建IOC容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-ioc01.xml");
// 2. 获取jdbc组件
JdbcTemplate jdbcTemplate = applicationContext.getBean(JdbcTemplate.class);
// 3. 进行数据库的crud操作
// 3.1 插入 删除 修改 DML update
String sql = "insert into students(name,gender,age,class) values(?,?,?,?)";
/*
* 参数一:sql语句
* 参数二: 传入占位符?的值 按顺序
* 返回值:int 影响行数
* */
int rows = jdbcTemplate.update(sql, "道格", "男", 25, "十年十班");
System.out.println(rows);
// 3.2 查询单条信息
// 按照 ID 查询一条学生信息 返回实体对象
sql = "select * from students where id = ?";
/*
* 参数一:sql语句
* 参数二:RowMapper 列名和属性名的映射器接口
* 参数三:Object...param 占位符 (这里是id数字)
* 返回值: rowMapper指定的对象 结果返回实体类
* */
Student queryStudent = jdbcTemplate.queryForObject(sql, (rs, rowNum) -> {
// 返回的结果集对象
// rs 结果集
// rowNum 行数
// rs 结果集中获取列的值 赋值给实体类对象即可
Student student = new Student();
student.setId(rs.getInt("id"));
student.setName(rs.getString("name"));
student.setGender(rs.getString("gender"));
student.setAge(rs.getInt("age"));
student.setClasses(rs.getString("class"));
return student;
}, 1);
System.out.println(queryStudent);
// 3.3 查询所有学生的信息
sql = "select id,name,gender,age,class as classes from students";
// BeanPropertyRowMapper 帮助我们自动映射列和属性值!要求列名和属性名一致!不一致需要起别名!
List<Student> studentList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Student>(Student.class));
System.out.println(studentList);
结果:
dao
service
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${doug.url}"/>
<property name="driverClassName" value="${doug.driver}"/>
<property name="username" value="${doug.username}"/>
<property name="password" value="${doug.password}"/>
bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="druidDataSource"/>
bean>
<bean id="stuDao" class="com.doug.dao.impl.StuDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
bean>
<bean id="stuService" class="com.doug.service.impl.StuServiceImpl">
<property name="stuDao" ref="stuDao"/>
bean>
<bean id="stuController" class="com.doug.controller.StuController">
<property name="stuService" ref="stuService"/>
bean>
@Test
public void testStuControllerMethod(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-02.xml");
StuController stuController = applicationContext.getBean(StuController.class);
stuController.findAllStu();
}
lambada