• Spring配置 + xml的IOC控制反转 + Setter注入


    简介

    Spring框架是一个容器,是整合其他框架的框架
    他的核心是IOC(控制反转)和AOP(面向切面编程),由20多个模块构成,在很多领域都提供了优秀的问题解决方案

    特点

    • 轻量级:由20多个模块构成,每个jar包都很小,小于1M,核心包也就3M左右
    • 代码污染小:Spring框架对程序员开发时的条条框框的约束较少,对代码的污染小
    • 面向接口编程:灵活性好,项目的可扩展性和可维护性都较高
    • 整合其他框架:使其他框架也更加易用
    • AOP:面向切面编程,将公共的,通用的,重复的代码单独开发,在需要时反织回去
    • 示例:

    示例分析:在开发中普遍需要使用到日志输出功能,会将日志输出功能大量耦合到项目的不同位置,如上图左侧所示。
    而日志输出功能与项目本身的核心业务逻辑无关,我们只是为了不时的查看程序的运行状态。则可以将日志功能单独提出去开发,在需要的地方将日志输出功能(所谓:切面)反织回去即可,如上图右侧所示。

    IOC

    • IOC(Inversion of Control):是一个概念,也是一种思想,由Spring容器进行对象的创建和依赖注入,程序员在使用时直接取用即可
    • 正转示例
    1. //程序员创建对象
    2. Student stu = new Student();
    3. //程序员进行赋值
    4. stu.setName("荷包蛋");
    5. stu.setAge(20);
    • 反转示例
    1. "stu" class="com.example.pojo.Student">
    2. "name" value="荷包蛋" />
    3. "age" value="20" />

    创建Spring项目

    • 创建maven的java项目:模板类型 + 项目目录结构 + 修改pom.xml文件添加基本配置的操作不再赘述,可以参考mybatis博客集里对maven项目的配置
    • 在pom.xml里添加Spring依赖
    1. <!-- 添加spring依赖-->
    2. <dependency>
    3. <groupId>org.springframework</groupId>
    4. <artifactId>spring-context</artifactId>
    5. <version>5.3.22</version>
    6. </dependency>
    • 在src/main/resources目录下添加Spring配置文件:applicationContext.xml(idea在下图状态下,无法截图,手机拍摄,包涵包涵)
    • 正常情况下,文件头自动补全

    创建实例对象:容器与手工创建对比

    • 实体类
    1. package com.example.pojo;
    2. public class Student {
    3. private String name;
    4. private int age;
    5. public Student() {
    6. System.out.println("无参方法被调用,Student实例被创建.....");
    7. }
    8. @Override
    9. public String toString() {
    10. return "Student{" +
    11. "name='" + name + '\'' +
    12. ", age=" + age +
    13. '}';
    14. }
    15. }
    • applicationContext.xml文件
    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    5. <bean id="stu" class="com.example.pojo.Student"/>
    6. beans>
    • 两种创建实例对象的对比
    1. package com.example.test;
    2. import com.example.pojo.Student;
    3. import org.junit.Test;
    4. import org.springframework.context.ApplicationContext;
    5. import org.springframework.context.support.ClassPathXmlApplicationContext;
    6. public class TestStudent {
    7. //测试程序员手动创建实例对象
    8. @Test
    9. public void testStudent(){
    10. Student stu = new Student();
    11. System.out.println(stu);
    12. }
    13. //测试Spring容器创建实例对象
    14. @Test
    15. public void testStudentSpring(){
    16. //创建Spring容器,并启动
    17. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    18. //从容器中获取对象
    19. Student stu = (Student) applicationContext.getBean("stu");
    20. System.out.println(stu);
    21. }
    22. }
    • 两次测试的输出结果均为
    1. 无参方法被调用,Student实例被创建.....
    2. Student{name='null', age=0}
    3. Process finished with exit code 0
    • 当Spring容器创建时,对应的应用域中注册的对象就会被创建
    1. @Test
    2. public void testStudentSpring(){
    3. //创建Spring容器
    4. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("source01/applicationContext.xml");
    5. }
    • 测试输出结果
    1. 无参方法被调用,Student实例被创建.....
    2. Process finished with exit code 0

    基于xml的setter注入

    1.简单类型(8 + 1)注入:使用value属性

    • 添加两个属性的set方法
    1. public void setName(String name) {
    2. this.name = name;
    3. }
    4. public void setAge(int age) {
    5. this.age = age;
    6. }
    • 使用setter注入法为实例对象的属性赋值
    1. <bean id="stu" class="com.example.pojo.Student">
    2. <property name="name" value="荷包蛋"/>
    3. <property name="age" value="20"/>
    4. </bean>
    • 测试Spring容器创建实例对象
    1. @Test
    2. public void testStudentSpring(){
    3. //创建Spring容器,并启动
    4. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("source01/applicationContext.xml");
    5. //从容器中获取对象
    6. Student stu = (Student) applicationContext.getBean("stu");
    7. System.out.println(stu);
    8. }
    • 测试输出
    1. 无参方法被调用,Student实例被创建.....
    2. Student{name='荷包蛋', age=20}
    3. Process finished with exit code 0

    2.引用类型注入:使用ref属性

    • 新增School类
    1. private String name;
    2. private String address;
    3. public void setName(String name) {
    4. this.name = name;
    5. }
    6. public void setAddress(String address) {
    7. this.address = address;
    8. }
    9. public School() {
    10. System.out.println("School类的构造方法被执行,实体对象被创建.....");
    11. }
    12. @Override
    13. public String toString() {
    14. return "School{" +
    15. "name='" + name + '\'' +
    16. ", address='" + address + '\'' +
    17. '}';
    18. }
    • Student对象持有School对象的引用
    1. private String name;
    2. private int age;
    3. private School school;
    4. public Student() {
    5. System.out.println("Student类的构造方法执行,实体对象被创建....");
    6. }
    7. public void setName(String name) {
    8. this.name = name;
    9. }
    10. public void setAge(int age) {
    11. this.age = age;
    12. }
    13. public void setSchool(School school) {
    14. this.school = school;
    15. }
    16. @Override
    17. public String toString() {
    18. return "Student{" +
    19. "name='" + name + '\'' +
    20. ", age=" + age +
    21. ", school=" + school +
    22. '}';
    23. }
    • applicationContext.xml文件
    1. <!-- 定义School实体类的实例对象-->
    2. <bean id="school" class="com.example.pojo02.School">
    3. <property name="name" value="nefu"/>
    4. <property name="address" value="哈尔滨"/>
    5. </bean>
    6. <!-- 定义Student实体类的实例对象 -->
    7. <bean id="stu" class="com.example.pojo02.Student">
    8. <property name="name" value="荷包蛋"/>
    9. <property name="age" value="20"/>
    10. <!-- 根据bean工厂中注册过的对象,进行依赖注入 -->
    11. <property name="school" ref="school"/>
    12. </bean>
    13. <!--
    14. 对于Student对象持有的School对象的引用
    15. 根据bean工厂中注册过的对象(不分注册先后),进行依赖注入
    16. (待注入属性类型必须和已经注册过的对象的类型一致,才可进行依赖注入)
    17. -->
    • 测试setter注入法的ref属性
    1. @Test
    2. public void testStudent(){
    3. //创建Spring容器,同时生成bean工厂中注册的对象
    4. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("source02/applicationContext.xml");
    5. //获取对象
    6. Student stu = (Student) applicationContext.getBean("stu");
    7. System.out.println(stu);
    8. }
    • 测试输出结果
    1. School类的构造方法被执行,实体对象被创建.....
    2. Student类的构造方法执行,实体对象被创建....
    3. Student{name='荷包蛋', age=20, school=School{name='nefu', address='哈尔滨'}}
    4. Process finished with exit code 0

    注意

    • 使用setter注入法必须提供无参构造方法,必须提供待注入属性的setXXX()方法,简单分析如下:无参构造方法用于创建实例对象,此时实例对象的属性是一张白纸,未被赋值和被其他数据污染对应属性的set方法是为了在底层调用时给目标属性赋值用,框架再封装,底层的执行代码该有的还要有,框架也不知道你在set方法中都想干些什么(毕竟set方法应该被用来赋值,但是不仅仅只能做赋值用)有了前两步,你便可以得到需要的对象,而且只有指定的属性被赋值,其他属性一尘不染但是,如果提供了有参构造方法,或者没有set方法,setter注入将会遇到无限多的麻烦无set方法,底层无法调用对应set方法完成属性赋值有参构造方法的参数会扰乱我们对指定属性的赋值计划例如,有参构造包括name和age两个属性,而set又要对name属性注入值,就会导致name属性被两次赋值,在创建对象时就这样做显然不合理所以,我们要做的就是,先创建一个干净的对象(无参构造,先不涉及属性值的问题),再用对应属性的set方法给属性赋值,做到精准赋值,按需操作

  • 相关阅读:
    暴力求解欲哭无泪之保安问题
    面向对象设计介绍和代码示例
    北京旅游HTML学生网页设计作品 dreamweaver作业静态HTML网页设计模板 北京旅游景点网页作业制作 HTML+CSS+JS
    Linux下 mtrace工具排查内存泄露问题
    算法竞赛入门【码蹄集进阶塔335题】(MT2301-2305)
    老杨说运维 | 六步法快速实现数据可视化,从容应对数字转型
    python中的属性管理机制
    jmeter压测GraphQL接口(两种方式)
    GB28181学习(十二)——报警事件通知和分发
    Java基础JDBC
  • 原文地址:https://blog.csdn.net/m0_67698950/article/details/126691135