Spring框架入门01-27:Spring基本概念和注入方式

Spring框架入门01-27:Spring基本概念和注入方式,第1张

Spring框架入门01-27:Spring基本概念和注入方式

开始时间:2021-12-14
课程地址

Spring概述

Spring 的核心是控制反转(IoC)和面向切面编程(AOP)。 Spring 是可以在 Java SE/EE 中使用的轻量级开源框架。

Spring 的主要作用就是为代码==“解耦”==,降低代码间的耦合度。 就是让对象和对象(模块和模块)之间关系不是使用代码关联,而是通过配置来说明。即在 Spring 中说明对象(模块)的关系。

Spring优点

Spring 是一个框架,是一个半成品的软件。有 20 个模块组成。它是一个容器管理对象,容器是装东西的, Spring 容器不装文本,数字。装的是对象。 Spring 是存储对象的容器。

  • 轻量
  • 针对接口编程,解耦合
  • AOP 编程的支持
  • 方便集成各种优秀框架
IoC 控制反转

控制反转(IoC, Inversion of Control),是一个概念,是一种思想。指将传统上由程序代码直接 *** 控的对象调用权交给容器,通过容器来实现对象的装配和管理。控制反转就是对对象控制权的转移,从程序代码本身反转到了外部容器。通过容器实现对象的创建,属性赋值,依赖的管理

  • 控制: 创建对象,对象的属性赋值,对象之间的关系管理。
  • 反转: 把原来的开发人员管理,创建对象的权限转移给代码之外的容器实现。 由容器代替开发人员管理对象。创建对象,
    给属性赋值。
  • 正转:由开发人员在代码中,使用new 构造方法创建对象, 开发人员主动管理对象。

当前比较流行的实现方式是依赖注入

用IoC的作用:目的就是减少对代码的改动, 也能实现不同的功能。 实现解耦合。

Java中创建的对象的方法:
java中创建对象有哪些方式:

  1. 构造方法 , new Student()
  2. 反射
  3. 序列化
  4. 克隆
  5. 动态代理
  6. ioc :容器创建对象

ioc的体现: servlet 参考博客
1: 创建类继承HttpServelt
2: 在web.xml 注册servlet , 使用

 myservlet 
com.bjpwernode.controller.MyServlet1
  1. 没有创建 Servlet对象, 没有 MyServlet myservlet = new MyServlet()
  2. Servlet 是Tomcat服务器它能你创建的。 Tomcat也称为容器
    Tomcat作为容器:里面存放的有Servlet对象, Listener , Filter对象
IoC技术实现

1.加入依赖
2.创建类
3.创建Spring配置文件
4.使用容器中的对象

依赖: classA 类中含有 classB 的实例,在 classA 中调用 classB 的方法完成功能,即 classA
对 classB 有依赖。

DI 是ioc的技术实现,
DI(Dependency Injection) :依赖注入, 只需要在程序中提供要使用的对象名称就可以, 至于对象如何在容器中创建,
赋值,查找都由容器内部实现。
spring是使用的di实现了ioc的功能, spring底层创建对象,使用的是反射机制
spring是一个容器,管理对象,给属性赋值, 底层是反射创建对象。

Spring 框架使用依赖注入(DI)实现 IoC。
Spring 容器是一个超级大工厂,负责创建、管理所有的 Java 对象,这些 Java 对象被称
为 Bean。

创建的前期工作和之前用maven创建module一样
File-New-Project 建立一个空的就行
然后新建module 选择maven-create from archetype 然后选择maven-archetype-quickstart

新建好的module中的pom.xml添加Spring依赖

    
      org.springframework
      spring-context
      5.2.5.RELEASE
    

以及添加插件

  
      
        
          maven-compiler-plugin
          3.1
          
            15
            15
          
        
      
  

然后创建beans.xml配置文件
src-main-resources-右键new一个XML configuration File-Spring Config
如果没有Spring config这个选项,一种是没有在pom.xml配置上面说的这个插件
另一个是由于IDEA不是旗舰版
如果都没问题,配置完插件后要刷新一下,才能生效找到这个Spring Config,通过这个xml创建beans.xml

spring的配置文件中
1.beans :是根标签,spring把java对象称为bean。
2.spring-beans.xsd是约束文件,和mybatis指定dtd是一样的。

在beans.xml中声明bean

    

声明bean ,就是告诉spring要创建某个类的对象
id:对象的自定义名称,唯一值。spring通过这个名称找到对象
class:类的全限定名称(不能是接口,因为spring是反射机制创建对象,必须使用类)
spring就完成 Someservice someservice = new SomeserviceImpl()

spring是把创建好的对象放入到map中, spring框架有一个map存放对象的。
springMap.put( id的值,对象);
例如 springMap.put(“someservice”, new SomeserviceImpl());

比较两种创建对象的方式

    @Test
    public void test01() {
        //主动创建对象
        SomeService service=new SomeServiceImpl();
        service.doSome();
    }

    @Test
    public void test02() {
        //使用spring容器创建的对象
        //1.指定spring配置文件的名称
        String config = "beans.xml";
        //2.创建表示spring容器的对象, ApplicationContext
        // ApplicationContext就是表示Spring容器,通过容器获取对象了
        // ClassPathXmlApplicationContext:表示从类路径中加载spring的配置文件
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);

        //从容器中获取某个对象, 你要调用对象的方法
        //getBean("配置文件中的bean的id值")
        //转了接口类型才能调用其方法
        SomeService service = (SomeService) ac.getBean("someService");

        //使用spring创建好的对象
        service.doSome();
    }

使用spring容器创建的对象
1.指定spring配置文件的名称
2.创建表示spring容器的对象, ApplicationContext
ApplicationContext就是表示Spring容器,通过容器获取对象了
ClassPathXmlApplicationContext:表示从类路径中加载spring的配置文件
从容器中获取某个对象, 你要调用对象的方法
getBean(“配置文件中的bean的id值”)
相当于给key拿value了

spring默认创建对象的时间:在创建spring的容器时,会创建配置文件中的所有的对象。
spring创建对象:默认调用的是无参数构造方法

当有多个spring bean对象时,可以通过以下语句获取对象信息
spring默认调用无参构造

    @Test
    public void test03(){
        String config="beans.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        //使用spring提供的方法, 获取容器中定义的对象的数量
        int nums  = ac.getBeanDefinitionCount();
        System.out.println("容器中定义的对象数量:"+nums);
        //容器中每个定义的对象的名称
        String names [] = ac.getBeanDefinitionNames();
        for(String name:names){
            System.out.println(name);
        }
    }

也可以获取非自定义类的对象
比如获得date对象
在bean配置文件中添加语句


    //获取一个非自定义的类对象
    @Test
    public void test04() {
        String config = "beans.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        //使用getBean();
        Date my = (Date) ac.getBean("mydate");
        System.out.println("Date:" + my);
    }
依赖注入

bean 实例在调用无参构造器创建对象后,就要对 bean 对象的属性进行初始化。
初始化是由容器自动完成的,称为注入。

根据注入方式的不同,常用的有两类: set 注入、构造注入。

set注入

set 注入也叫设值注入是指,通过 setter 方法传入被调用者的实例。这种注入方式简单、
直观,因而在 Spring 的依赖注入中大量使用。

简单类型的赋值

创建Student类对象
只需要加set方法,不需要加get方法

package BUPT.ba01;

public class Student {
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}

在resource里面配置
这里即使是int类型,也要加双引号
这是xml文件的要求

    
        
        
    

通过property来实现赋值,调用的是Student类的set方法

测试方法里面进行测试

package BUPT;

import BUPT.ba01.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppTest {
    @Test
    public void test02() {
        //使用spring容器创建的对象
        //1.指定spring配置文件的名称
        String config = "ba01/applicationContext.xml";
        //2.创建表示spring容器的对象, ApplicationContext
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        Student mystudent = (Student) ac.getBean("myStudent");
        System.out.println(mystudent);
    }
}


但也要注意,虽然明说是set+属性名这样进行赋值
其实他看的不是Student类里面定义的属性,而是找的对应的set方法
比如我没有定义一个属性叫email
但是我在Student类里面设置了一个方法叫 setEmail()

    public void setEmail(String email) {
        System.out.println("输出的是自定义set方法的email" + email);
    }

配置文件也给一个

       

那他依然会自动调用这个方法

因为他找的是property后面这个name 再去Student类里找对应的setName方法

引用类型的赋值

在实体类新建一个school类
并设置school类为Student类的一个属性
school类

public class School {
    private String address;
    private String name;
    }

Student类

public class Student {
    private String name;
    private int age;
    public School school;

//setName setAge以及toString重写省略了,实际是有的
    public void setSchool(School school) {
        System.out.println("school:" + school);
        this.school = school;
    }
}

新增配置

    
        
        
    

此时再修改Student的xml配置

 
        
        
        
    

注意引用类型通过ref="id"实现的

构造注入

就是调用Student里面的constructor来协助创建对象

Student类里面加一个构造函数

public Student(String name, int age, School school) {
        this.name = name;
        this.age = age;
        this.school = school;
    }

配置文件中使用constructor

    
        
        
        
    

    
        
        
    
自动注入

只对引用类型有效

  • byName:当配置文件中被调用者 bean 的 id 值与代码中调用者 bean 类的属性名相同时,可使用
    byName 方式,让容器自动将被调用者 bean 注入给调用者 bean。
  • byType:配置文件中被调用者 bean 的 class 属性指定的类,要与代码中调用者 bean 类的某引用类型属性类型同源。即要么相同,要么有 is-a 关系(父子类,或是接口-实现类)。但这样的同源的被调用 bean 只能有一个。多于一个,容器就不知该匹配哪一个了。

我们来看byName的一个示例
在配置bean id时,后面加一个 autowire “byName”
因为我们在Student类里面调用School这个类时是这样初始化的

    public School school;

所以我们把这个school 作为School类的id名
让他俩匹配在一起,此时就可以进行自动注入了

 
        
               
    

    
        
        
    

再来看byType
将autowire后面的值改为 byType

         
        
        
    

    
        
        
    

这种的byType比较好理解,因为用school传school

那么我们再看一种情况
新建一个中学类extends学校类
然后配置文件写下面的内容

    
        
        
    

可以看到该类属于school类的子类,仍然可以自动注入
但如果有多个子类或者父类子类都写在bean里面,会报错,不知道注入谁

多配置文件
  • 每个文件的大小比一个文件要小很多。效率高
  • 避免多人竞争带来的冲突。

如果你的项目有多个模块(相关的功能在一起) ,一个模块一个配置文件。
学生考勤模块一个配置文件,张三
学生成绩一个配置文件,李四

多文件的分配方式:

  1. 按功能模块,一个模块一个配置文件
  2. 按类的功能,数据库相关的配置一个文件配置文件, 做事务的功能一个配置文件, 做service功能的一个配置文件等

将之前的一个拆分一下
school一个

    
        
        
    

student一个

    
        
        
    

然后总的来一个,用来import子配置文件

    
    

也能正常使用
在total里面也可以使用通配符来import,放在同一级的目录下,才能读取
这样的话要注意total自身的一个命名,不能把自己也包含进去了,防止自己调用自己

    

结束时间:2021-12-16

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5672860.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存