• Spring入门知识以及项目搭建与依赖注入


    Spring基础知识了解

    Spring官网:https://spring.io/

    什么是Spring?

    Spring是与2003年新奇的一个轻量级的java开发框架,它是为了解决企业引用开发的复杂新二创建的。Spring的核心是控制反转(IOC)和面向切面编程(AOP)

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

    Spring根据代码的功能特点,使用IOC降低业务之间耦合度。IOC是的主业务在相互调用过程中,不用自己维护关系了,即不用自己创建需要使用的对象了。而是由Spring容器统一管理,自动“注入”,即就是自动赋值。使用AOP使得系统级服务得到最大的复用,且不用再由程序员手动将系统服务“混杂”到主业务逻辑中了,而是有Spring容器统一完成。

    总之:Spring是一个容器,它是整合其他框架的框架,它的核心是IOC和AOP,它是由20多个模块组成。

    耦合度:事物之间的关联程度。比如一块布耦合度非常高,用这块布做的衣服,耦合度就相对低一点。

    Spring的特点

    1. 轻量级。由20多个模块构成,每个jar包都很小,核心包就3M左右
    2. 面向接口编程。使用接口,项目的可维护性,可扩展性都高。接口不关心实现类的类型,使用接口指向实现类,切换实现类即可换整个功能。
    3. AOP:面向切面编程。三层式开发:界面层、业务逻辑层、数据访问层会有公共的逻辑或者业务处理,重复的代码,我们会提出来单独写,谁用谁取。那些公共的代码就是切面。公共的提取出来,需要的时候反置回去,就是面向切面编程,底层的原理是动态代理。
    4. 整合其他框架。整合后使其他框架更易用。

    Spring的体系结构

    在这里插入图片描述

    Data Access(数据库整合):

    JDBC, ORM, OXM, JMS, Transaction

    Web(MVC Web 开发):

    Web, Servlet, Portlet, Struts

    AOP(切面编程)

    AOP 框架: Aspects

    JVM的代理:Instrumentation;

    发送消息:Messaging;

    Core Container(核心容器):

    Beans: 管理 Beans

    Core: Spring 核心

    Context: 配置文件

    ExpressionLanguage: SpEL 表达式

    Test(Junit 整合)

    什么是IOC?

    控制反转IOC(Inversion of Control)是一种思想。由于Spring容器进行对象的创建和依赖注入。程序员取出直接使用。

    正转:由程序员创建对象和依赖注入称为正转。

    Student student = new Student();
    student.setName("张三");
    
    • 1
    • 2

    反转:由Spring容器创建对象和依赖注入称为反转,将控制权从程序员手中夺走。

    <bean id="student" class="com.www.spring.demo.Student">
            <property name="id" value="100"/>
            <property name="account" value="张三"/>
        bean>
    
    • 1
    • 2
    • 3
    • 4

    项目搭建

    1. 搭建项目
    2. 更改pom.xml文件。添加spring核心依赖
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-contextartifactId>
        <version>5.2.2.RELEASEversion>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 创建实体类。
    public class Admin {
        private Integer id;
        private String name;
        private String num;
        private String account;
    
        public Admin(Integer id, String name, String num) {
            this.id = id;
            this.name = name;
            this.num = num;
        }
    
        public Admin() {
        }
    
        public void doSome() {
            System.out.println("执行此方法");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    1. 添加applicationContext.xml文件,用于创建对象。
    2. 在applicationContext.xml文件中添加bean标签。
    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        
        <bean id="admin" class="com.www.spring.modle.Admin"/>
    beans>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    1. 测试
    public void test1(){
            //使用Spring容器创建的对象  默认调用无参构造
            //1.指定spring配置文件的名称
            String config = "applicationContext.xml";
            //2.创建表示spring容器的对象  ApplicationContext
            //ApplicationContext 表示spring的容器
            //ClassPathXmlApplicationContext:表示从类路径中加载spring的配置文件
            ApplicationContext ac = new ClassPathXmlApplicationContext(config);//此时构造方法执行,创建对象
        //在创建spring对象时会创建配置文件中所有的对象
    
            //从容器中获取某个对象,要调用对象的方法
            //getBean("配置文件中的bean的id值")
            Admin admin = (Admin) ac.getBean("admin");
    
            admin.doSome();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    以上创建对象的过程虽然看起来过程复杂,且漫长,但是有没有发现此过程中我们是没有new过的,直接通过配置文件以及名字就创建对象了。

    spring中常用到的方法

        public void test2(){
            String config = "applicationContext.xml";
            ApplicationContext ac = new ClassPathXmlApplicationContext(config);
            //getBeanDefinitionCount():容器中定义的对象的个数
            int nums = ac.getBeanDefinitionCount();
            System.out.println("容器中定义的对象的个数"+nums);
            //getBeanDefinitionNames():容器中定义的每个对象的名字
            String names[] = ac.getBeanDefinitionNames();
            for (String name : names) {
                System.out.println(name);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    创建非自定的对象:

    <bean id="mydate" class="java.util.Date"/>
    
    
    • 1
    • 2
    • 3
    • 4

    依赖注入(di)

    di:创建对象并给属性赋值。

    两种实现方法:

    1. 在spring的配置文件中,使用标签和属性完成,叫做基于XML的di实现
    2. 使用spring中的注解,完成属性赋值,叫做基于注解的di实现

    基于XML的di

    1. set注入(设值注入):spring调用类的set方法,在set方法可以实现属性的赋值。
    
    <bean id="student" class="com.www.spring.modle.Student">
            <property name="name" value="张三"/>
            <property name="id" value="1"/>
            <property name="num" value="1001"/>
    bean>
     
    <bean id="student1" class="com.www.spring.modle.Student">
        <property name="name" value="张四"/>
        <property name="id" value="2"/>
        <property name="num" value="1002"/>
        <property name="admin" ref="admin"/>
    bean>
    <bean id="admin" class="com.www.spring.modle.Admin">
        <property name="name" value="admin"/>
        <property name="id" value="1"/>
    bean>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    1. 构造注入,spring调用类的有参构造方法,创建对象,在构造方法中完成赋值。

    使用constructor-arg标签
    一个constructor-arg标签表示构造方法的一个参数
    name:属性表示构造方法的形参名
    index:表示构造方法的参数的位置,从左往右 0 1 2 3…
    ref:构造方法的形参是引用类型
    value:构造方法的形参是简单类型

       
        <bean id="student2" class="com.www.spring.modle.Student">
            <constructor-arg name="name" value="张武">constructor-arg>
            <constructor-arg name="num" value="1003">constructor-arg>
            <constructor-arg name="admin" ref="admin">constructor-arg>
        bean>
        
        <bean id="student3" class="com.www.spring.modle.Student">
            <constructor-arg index="1" value="1004">constructor-arg>
            <constructor-arg index="0" value="张流">constructor-arg>
            <constructor-arg index="2" ref="admin">constructor-arg>
        bean>
        
        <bean id="student4" class="com.www.spring.modle.Student">
            <constructor-arg  value="张流">constructor-arg>
            <constructor-arg  value="1004">constructor-arg>
            <constructor-arg  ref="admin">constructor-arg>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    引用类型的自动注入

    引用类型的自动注入:Spring框架根据某些规则给引用类型赋值。不用自己给引用类型赋值使用的规则常用的是byName,byType。

    byName(按名称注入)
    1. byName(按名称注入):java类中引用类型的属性名和spring容器中(配置文件中)bean的id名称一样,且数据类型是一致的,这样的容器中的bean,spring能够赋值给引用类型。
        <bean id="student5" class="com.www.spring.modle.Student" autowire="byName">
            <property name="name" value="张其"/>
            <property name="id" value="7"/>
            <property name="num" value="1007"/>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    byType(按类型注入)

    2.byType(按类型注入):java类中引用类型的数据类型和spring容器中(配置文件)bean的class属性是同源关系的,这样的bean可以赋值给引用类型
    同源的意思

    1. java类中引用类型的数据类型和bean的class的值是一样的
    2. java类中引用类型的数据类型和bean的class的值是父子类关系的。
    3. java类中引用类型的数据类型和bean的class的值是接口和实现类的关系

    注 : byType中, 在xml中声明的bean只能有有一个符合条件的

     <bean id="student6" class="com.www.spring.modle.Student" autowire="byName">
            <property name="name" value="张其"/>
            <property name="id" value="7"/>
            <property name="num" value="1007"/>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    使用多配制文件

    当类的声明非常多的时候,将所有的声明都放在一个配置文件中是不可取的;在做项目的时候,多人使用同一个配置文件时,是及其容易出现错误的;

    多配制文件的优势

    1. 每个文件的大小比一个文件小得多,易操作,效率高。
    2. 避免多人竞争带来的冲突。

    多文件的分配方式

    1. 如果项目由多个模块构成,建议一个模块一个配置文件。
    2. 按类的功能,数据库相关配置一个文件,做事务的功能一个配置文件,做service功能一个配置文件。

    具体操作

    
        <bean id="student" class="com.www.spring.modle.Student" autowire="byType">
            <property name="name" value="张其"/>
            <property name="id" value="7"/>
            <property name="num" value="1007"/>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
     
        <bean id="admin" class="com.www.spring.modle.Admin">
            <property name="name" value="admin"/>
            <property name="id" value="1"/>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    
        
        <import resource="classpath:be01/spring-Student.xml"/>
        <import resource="classpath:be01/spring-Admin.xml"/>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    public void test4(){
        //加载总文件
            String config = "be01/spring-Total.xml";
            ApplicationContext ac = new ClassPathXmlApplicationContext(config);
            Student student = ac.getBean("student",Student.class);
            System.out.println(student);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    以上主配置文件中import可以使用通配符

    
        <import resource="classpath:be01/spring-*.xml"/>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    基于注解的di

    使用注解的步骤:
    1. 加入maven的依赖;早在加入spring-context时就已经间接加入了spring-aop,所以不需要再添加。
    2. 在类中加入spring的注解;
    3. 在spring的配置文件中,加入一个组件扫描的标签,说明注解的位置。
    <context:component-scan base-package="com.www.spring"/>
    
    • 1

    添加完component-scan标签后配置文件会多出:

    xmlns:context="http://www.springframework.org/schema/context"
    http://www.springframework.org/schema/context
    https://www.springframework.org/schema/context/spring-context.xsd
    
    • 1
    • 2
    • 3
    1. 使用注解
    常用的注解:
    1. @component:创建对象的,相当于bean标签的功能,属性value就是对象的名称,也就是bean中的id值,value的值时惟一的,创建的对象在整个spring容器中是惟一的,创建对象时调用构造方法,注解的位置:类的上面。
    //写法1:
    //@component(value = “admin)
    //等同于
    
    //写法2:省略value
    //@component(指定对象的名称)
    
    //写法3:不指定对象的名称,由spring默认名称:首字母小写的类名。
    //@component
    
    
    @Component(value = "admin")//等同于
    public class Admin {
        private Integer id;
        private String name;
        private String num;
        private String account;
    
        public Admin(String name, String num, String account) {
            this.name = name;
            this.num = num;
            this.account = account;
        }
    
    
        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 getNum() {
            return num;
        }
    
        public void setNum(String num) {
            this.num = num;
        }
    
        public String getAccount() {
            return account;
        }
    
        public void setAccount(String account) {
            this.account = account;
        }
    
        public Admin(Integer id, String name, String num) {
            this.id = id;
            this.name = name;
            this.num = num;
        }
    
        public Admin() {
            System.out.println("无参构造方法");
        }
    
        public void doSome() {
            System.out.println("执行此方法");
        }
    
        @Override
        public String toString() {
            return "Admin{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", num='" + num + '\'' +
                    ", account='" + account + '\'' +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    1. @Respotory:(用在持久层上面的)与@component功能一致,创建的是dao对象,dao对象是能访问数据库的。

    2. @service:(用在业务逻辑层类上面的) 与@component功能一致,放在service的实现类上面,创建service对象,service对象是做业务处理,可以有事务功能的。

    3. @controller:(用在控制器上面的)与@component功能一致,放在控制器(处理器)类的上面,创建控制器对象的,控制器对象,能够接受用户提交的参数,显示请求结果。

    以上注解与@component功能一致,语法相同,但是各自还有额外功能,他们是给项目分层的。

    1. @value:为简单类型赋值,使用此注解时,必须已经创建对象
    /*
           可以写在属性定义的上面,无需set方法,比较常用
           也可以写在set方法上面
         */
    
    @Component("student")
    @Data
    public class Student {
        private Integer id;
        @Value( "张吧")
        private  String name;
        @Value(value = "1008")
        private String num;
    
        private Admin admin;
    
        public Student() {
        }
    
        public Student(String name, String num, Admin admin) {
            this.name = name;
            this.num = num;
            this.admin = admin;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    1. @Autowired:spring框架提供的注解,实现引用类型的赋值。spring中通过注解给引用类型赋值,使用的是自动注入原理,支持byType,byName。默认使用byTy自动注入。
     @Autowired
    private Admin admin;
    
    • 1
    • 2

    如果使用byName的方式:需要借助@Qualifier(value = “对象名称”)

    	@Autowired
        @Qualifier(value = "admin")//这里的admin是Admin类创建对象的名称,相当于bean的id
        private Admin admin;//这里的admin是Student类中属性名
    //两个注解不分先后
    
    • 1
    • 2
    • 3
    • 4

    @Autowired中有一个属性:required

    required=true :表示引用类型赋值失败,程序终止,程序报错

    required=false:表示引用类型赋值失败,程序不终止,引用类型为null

    1. @Resource:来之jdk中的注解,spring提供了jdk中@Resource注解的支持,该注解可以支持byType、byName方式,默认是byName。

    先使用byName自动注入,如果byName赋值失败,再改用byType自动注入。

    只想使用byName一种方式时:

    @Resource(name = "admin")
        private Admin admin;
    
    • 1
    • 2

    注解与xml配置文件对比

    配置文件:

    优点:代码和值是完全分开的,对于经常改值的,可以用配置文件;

    缺点:语法繁杂,与代码完全分开,浏览源代码时,不知道对应的值。

    注解:

    优点:快捷方便,速度快,代码简洁;不经常改变的用注解比较方便

    缺点:硬编入java代码中,修改后需要重新编译

  • 相关阅读:
    React如何实现国际化?
    使用requests库进行网络爬虫:IP请求错误的解决方法
    Zotero——一款文献管理工具
    交换机与路由技术-32-命名ACL
    访问者模式:对象结构的元素处理
    Java的本地方法栈
    35、CSS进阶——行盒的垂直对齐以及图片底部白边
    【网络编程】okhttp源码解析
    基于聚集诱导荧光探针细胞膜/细胞膜表面GABA受体荧光探针/上汞离子荧光探针的研究
    Web自动化xpath定位法实现
  • 原文地址:https://blog.csdn.net/qq_55931044/article/details/126365827