SpringIoc讲解

由于作者水平有限只是对学习过程中遇到的资料进行总结一下,中间可能会有部分错误,如若发现,请在评论区指正,万分感谢。

spring与springioc的关系

Spring IoC 是 Spring 框架中用于实现对象之间解耦的核心机制,而 Spring 则是一个基于 IoC 的全面框架,提供了众多的功能模块和工具,帮助开发者更加高效地开发企业级应用。

spring容器的作用

1. 控制反转的ioc

早期程序员根据配置文件 编写Java代码创建对象 权力指向程序员 但是现在由spring核心容器 在ioc容器中完成实例化反射 权力指向了spring容器。
SpringIoc讲解_第1张图片

2. DI

注入依赖和依赖注入

A-B注入这个过程只需要配置文件后使用ioc容器完成即可
DI 是指将一个对象所需要的依赖关系(其他对象或值)从外部传递给它,而不是让对象自行创建这些依赖关系。换句话说,对象不再负责自己的依赖项的创建和解析,而是由容器负责,容器会在运行时动态地将依赖项注入到对象中。
作用:DI 是一种非常有用的设计模式,它可以帮助开发者更好地管理对象之间的依赖关系,实现对象之间的解耦,从而提高代码的可维护性、可测试性和复用性。在 Spring 框架中,DI 是通过 IoC 容器来实现的,开发者只需要定义对象之间的依赖关系,由容器来负责对象的创建和依赖注入。

知道spring的组成之后我们来学习一下ioc/di的实现步骤

SpringIoc讲解_第2张图片
这张图片的过程很明确,现在我们来学习一下怎么使用配置文件 创建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是实现三层架构的效果

创建项目 文件,进行基本内容的配置

  1. 配置数据库驱动和连接池
  2. 配置druid
  3. 配置jdbc
  4. 配置springcontext依赖
完整内容
    <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>jakarta.annotationgroupId>
            <artifactId>jakarta.annotation-apiartifactId>
            <version>2.1.1version>
        dependency>

        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-jdbcartifactId>
            <version>6.0.6version>
        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;
    }
}
代码讲解
  1. 创建需要的jdbcTemplate对象,因为起到储存作用的就是这个对象内容,由于是私有化属性,那么我们就设置一个setter方法。
  2. 实现接口中的需求功能 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;
    }
}
代码讲解
  1. 创建一个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的配置

  1. 配置bean连接外层配置文件
 <context:property-placeholder location="classpath:jdbcTemplate.properties"/>
  1. 配置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>
  1. 将jdbc与druid进行连接
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="druidDataSource"/>
    bean>
  1. 注入三层依赖-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层
SpringIoc讲解_第3张图片

你可能感兴趣的:(ssm,springioc,ssm,springioc)