由于作者水平有限只是对学习过程中遇到的资料进行总结一下,中间可能会有部分错误,如若发现,请在评论区指正,万分感谢。
spring与springioc的关系
Spring IoC 是 Spring 框架中用于实现对象之间解耦的核心机制,而 Spring 则是一个基于 IoC 的全面框架,提供了众多的功能模块和工具,帮助开发者更加高效地开发企业级应用。
spring容器的作用
1. 控制反转的ioc
早期程序员根据配置文件 编写Java代码创建对象 权力指向程序员 但是现在由spring核心容器 在ioc容器中完成实例化反射 权力指向了spring容器。
2. DI
注入依赖和依赖注入
A-B注入这个过程只需要配置文件后使用ioc容器完成即可
DI 是指将一个对象所需要的依赖关系(其他对象或值)从外部传递给它,而不是让对象自行创建这些依赖关系。换句话说,对象不再负责自己的依赖项的创建和解析,而是由容器负责,容器会在运行时动态地将依赖项注入到对象中。
作用:DI 是一种非常有用的设计模式,它可以帮助开发者更好地管理对象之间的依赖关系,实现对象之间的解耦,从而提高代码的可维护性、可测试性和复用性。在 Spring 框架中,DI 是通过 IoC 容器来实现的,开发者只需要定义对象之间的依赖关系,由容器来负责对象的创建和依赖注入。
知道spring的组成之后我们来学习一下ioc/di的实现步骤
这张图片的过程很明确,现在我们来学习一下怎么使用配置文件 创建bean对象,以及依赖注入怎么实现
我们必须明确一件事情 DI 过程中包括实例化 Bean 和注入依赖两个主要步骤 实例化bean主要就是指向的是构造函数 。
在 DI 过程中,首先需要实例化被注入的 Bean 对象。这可以通过调用 Bean 的构造函数来创建一个新的实例。如果使用的是无参构造函数,则直接调用构造函数即可实例化对象。如果使用的是有参构造函数,则需要提供构造函数所需的参数值,可以在 XML 配置文件中使用 元素指定参数值。
一旦 Bean 对象实例化完成,接下来就是注入依赖。这可以通过调用 Bean 的 setter 方法或者直接设置 Bean 的字段来完成。在 XML 配置文件中,可以使用 元素来设置属性的值,或者使用 元素来指定构造函数参数的值。
1.无参构造函数
public class Person {
Person() {
}
}
无参构造实现配置
<bean id="person" class="com.code.Person"/>
2.有参构造函数
public class Person {
String name;
Person(String name) {
this.name = name;
}
}
有参函数的配置
<bean id="person" class="com.code.Person">
<constructor-arg value="person"/>
</bean>
多个参数的有参构造
public class Person {
String name;
Integer age;
String address;
public Person(String name,Integer age,String address){
this.name = name;
this.age = age;
this.address = address;
}
}
多个参数的有参函数的配置
<bean id="person" class="com.example.Person">
<constructor-arg name="name" value="张三"/>
<constructor-arg name="age" value="20"/>
<constructor-arg name="address" ref="address"/>
</bean>
在 Spring 中,我们可以使用工厂方法来创建对象。这些工厂方法可以是静态的,也可以是非静态的。
静态工厂方法:静态工厂方法是指定义在一个类中,并使用 static 关键字修饰的工厂方法。在 Spring 中,我们可以使用 元素的 factory-method 属性来指定要调用的静态工厂方法。
静态工厂方法(一)
public class ShapeFactory {
public static Shape createCircle() {
return new Circle();
}
public static Shape createSquare() {
return new Square();
}
}
静态工厂方法配置(一)
<beans>
<bean id="circle" class="com.example.Circle" factory-method="createCircle"/>
<bean id="square" class="com.example.Square" factory-method="createSquare"/>
</beans>
静态工厂方法(二)
public class Person {
private static Person person = new Person();
private Person (){}
public static Person creatPerson(){
return person;
}
}
对应的配置文件
<bean id="person" class="com.code.Person" factory-method="creatPerson"/>
相当于直接进行调用了,返回的对象是唯一的,减少创建 保证线程安全 类似于饿汉,单例模式
非静态工厂方法的配置文件
public interface ShapeFactory {
Shape createShape();
}
public class CircleFactory implements ShapeFactory {
public Shape createShape() {
return new Circle();
}
}
public class SquareFactory implements ShapeFactory {
public Shape createShape() {
return new Square();
}
}
配置文件
<beans>
<bean id="circleFactory" class="com.example.CircleFactory"/>
<bean id="squareFactory" class="com.example.SquareFactory"/>
<bean id="circle" factory-bean="circleFactory" factory-method="createShape"/>
<bean id="square" factory-bean="squareFactory" factory-method="createShape"/>
</beans>
多个参数的有参构造写法
私有化属性
class Address{ }
public class Person {
private Address address;
private Integer age;
public Person(Integer age){
this.age = age;
}
}
私有化属性的配置
<bean id="person" class="com.example.Person">
<constructor-arg name="age" value="20"/>
<property name="address">
<bean class="com.example.Address"/>
</property>
</bean>
创建ioc容器
先根据配置创建ioc容器 从容器中获取配置的bean对象 使用对象进行调用
获取容器有三种方法,你可以根绝需求选择对应的容器,选择和合适的方法创建和使用
举例:
@Test
public void getBeanFromIoc() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("demo-01.xml");
// 查找是根据beanid进行的查找
// 如果ioc容器存在多个同类型的bean会出现问题
// ioc的配置一定是实现类 创建的bean是实例化 可以使用多态 但是 指向的配置文件一定是接口的实现类
HelloWorld helloWorld = applicationContext.getBean("helloWorld", HelloWorld.class);
helloWorld.doWork();
}
FactoryBean
FactoryBean是Spring框架中的一个接口,它允许开发人员定制化地创建和配置bean实例。通常情况下,使用工厂模式创建bean时,需要编写一个工厂类来负责bean的创建和初始化。而使用FactoryBean接口可以将这些工厂类封装起来,使得在配置Spring容器时更加方便。
实现FactoryBean接口的类需要提供自定义的逻辑来创建bean实例,并且该类本身也会成为Spring容器中的一个bean。通过FactoryBean可以实现更加灵活的bean创建和初始化过程,例如根据不同条件创建不同的实例,或者对属性进行特殊处理。
当Spring容器遇到实现了FactoryBean接口的bean定义时,它会调用FactoryBean的方法来获取实际的bean实例,而不是直接返回FactoryBean本身。这样的设计允许开发人员在创建bean时进行更多的定制化操作,从而满足复杂的业务需求。
需求代码
import org.springframework.beans.factory.FactoryBean;
public class MyBeanFactory implements FactoryBean<MyBean> {
private String someProperty;
// 设置属性
public void setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
// 返回bean实例
@Override
public MyBean getObject() throws Exception {
MyBean myBean = new MyBean();
myBean.setSomeProperty(someProperty);
return myBean;
}
// 返回bean的类型
@Override
public Class<?> getObjectType() {
return MyBean.class;
}
// 是否是单例
@Override
public boolean isSingleton() {
return true;
}
}
配置信息
<bean id="myBean" class="com.example.MyBeanFactory">
<property name="someProperty" value="someValue"/>
</bean>
实战-使用jdbcTemplate是实现三层架构的效果
创建项目 文件,进行基本内容的配置
- 配置数据库驱动和连接池
- 配置druid
- 配置jdbc
- 配置springcontext依赖
完整内容
<dependencies>
<!--spring context依赖-->
<!--当你引入SpringContext依赖之后,表示将Spring的基础依赖引入了-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.6</version>
</dependency>
<!-- 数据库驱动和连接池-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.0.6</version>
</dependency>
</dependencies>
配置这部分内容按照正常的maven配置即可
创建dao层(持久化储存层)
我们采取接口和实现类的形式编写这个模块的内容
接口
package com.ssmlearn.dao;
import com.ssmlearn.pojo.Student;
import java.util.List;
public interface StudentDemo {
List<Student> querryAll();
}
实现类
package com.ssmlearn.dao;
import com.ssmlearn.pojo.Student;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
public class StudentDaoImpl implements StudentDemo{
private JdbcTemplate jdbcTemplate;
// 这个是提供的set方法
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
// 这个是实现的方法
@Override
public List<Student> querryAll() {
String sql ="select * from students";
List<Student> students = jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(Student.class));
System.out.println("Dao层内容"+students);
return students;
}
}
代码讲解
- 创建需要的jdbcTemplate对象,因为起到储存作用的就是这个对象内容,由于是私有化属性,那么我们就设置一个setter方法。
- 实现接口中的需求功能 queryAll()方法 ,编写sql语句,使用的是查找数据库students中的所有内容 使用jdbcTemplate对象中的query方法,将sql语句和Java连接起来
new BeanPropertyRowMapper<>(Student.class) 是使用 BeanPropertyRowMapper 创建一个泛型为 Student 的实例对象。该对象可以被传递给 JdbcTemplate 的 query() 方法,用于将查询结果映射为 Student 类型的对象列表。
service层代码 业务逻辑层
接口代码
package com.ssmlearn.service;
import com.ssmlearn.pojo.Student;
import java.util.List;
public interface FindAll {
public List<Student> findAll();
}
实现类
package com.ssmlearn.service.iml;
import com.ssmlearn.dao.StudentDaoImpl;
import com.ssmlearn.pojo.Student;
import com.ssmlearn.service.FindAll;
import java.util.List;
public class FindAllimpl implements FindAll {
private StudentDaoImpl studentDao;
// setter方法
public void setStudentDao(StudentDaoImpl studentDao) {
this.studentDao = studentDao;
}
@Override
public List<Student> findAll() {
List<Student> students = studentDao.querryAll();
System.out.println("Service"+students);
return students;
}
}
代码讲解
- 创建一个dao层实现类对象,然后实现业务逻辑,返回信息给控制层,这里面主要是体现了对dao层持久化储存的调用,该处未进行筛选代码,体现的不明显。
Constroller代码编写
package com.ssmlearn.constroller;
import com.ssmlearn.pojo.Student;
import com.ssmlearn.service.iml.FindAllimpl;
import java.util.List;
public class StudentConstroller {
FindAllimpl findAllimpl;
public void setFindAllimpl(FindAllimpl findAllimpl) {
this.findAllimpl = findAllimpl;
}
public void findAll(){
List<Student> all = findAllimpl.findAll();
System.out.println("最终结果"+all);
}
}
这个主要是跟前端交互的内容,这里直接创建services层的代码,然后进行调用。
完成这部分内容之后,我们需要进行Di的配置
- 配置bean连接外层配置文件
<context:property-placeholder location="classpath:jdbcTemplate.properties"/>
- 配置druid
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${atguigu.url}"/>
<property name="driverClassName" value="${atguigu.driver}"/>
<property name="username" value="${atguigu.username}"/>
<property name="password" value="${atguigu.password}"/>
</bean>
- 将jdbc与druid进行连接
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="druidDataSource"/>
</bean>
- 注入三层依赖-dao层注入到service层,service层注入到constroller层
<bean id="studentDao" class="com.ssmlearn.dao.StudentDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<bean id="findAllimpl" class="com.ssmlearn.service.iml.FindAllimpl">
<property name="studentDao" ref="studentDao"></property>
</bean>
<bean id="studentConstroller" class="com.ssmlearn.constroller.StudentConstroller">
<property name="findAllimpl" ref="findAllimpl"/>
</bean>
完成配置信息之后,我们需要进行测试,选取单元测试,使用注解的形式进行测试内容
单元测试
@Test
void testIoc(){
// 1.创建一个ioc容器
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spirng-ioc-02.xml");
// 2.获取一个控制层的对象实例 这个是通过ioc根绝配置自动完成的
StudentConstroller bean = applicationContext.getBean(StudentConstroller.class);
// 3.调用bean对象的方法
bean.findAll();
// 4.释放
applicationContext.close();
}
最终运行:最终结果体现在constroller层