spring基于5.3.0GA版本-笔记

Spring

框架的作用:解耦和(降低耦性)

形成生态(让更多的人用或者使用的人很多,说明这个东西很好)

一、spring初识

1.1、框架

人话:

举个例子,现在的楼盘都相当于毛坯房,我们买到的毛坯房都是一模一样的,这个毛坯房就相当于框架,我们可以添加东西,让他具备一定的风格。不同的人有不同的装修风格,所以毛坯房都一样,但是装修风格不同,所得到的成品就不同,简单来说,就相当一件房子的模型已经固定好了,你可以随意往里面添加东西。看自己具体怎么设计。

切换到我们所编写的应用来说,所依赖的固定的东西,别人已经给定义好了,给提供好了架子,自己只需要拿这个架子来往里面添加东西,实现我们的功能即可。

1.2、技术架构演变

image-20210105195434451

  1. 单一应用架构

    当访问量很小,只有几十人或者几百人来访问这个应用的话,我们可以把所有的功能都部署在一起,比如初学Javase时写的小demo。耦合度很高。

    image-20210125100414309

    ​ 这种架构只适合小规模的访问量,不适合大型的互联网架构,当访问量变大时,就不适合,这种架构单点容错低,并发能力差。代码耦合度高,开发维护困难。

  2. 垂直应用架构

    当访问量变大时,就需要分不同的层级,来解耦合,让耦合度降低,方便增改程序,例如:SSM

    image-20210125101211588

  1. 分布式架构

    当垂直应用越来越多,应用之间交互越发频繁,把核心的业务抽取出来作为独立的服务,逐渐形成稳定的服务中心

image-20210125101122635

  1. 流动计算架构(SOA)

    image-20210125102738106

    服务越来越多、容量的评估和小服务资源浪费的问题逐渐出现,此时需要增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。

    用户提高机器利用率的资源调度和治理中心(SOA)是关键。

    以前出现了什么问题?

    • 服务越来越多,需要管理每个服务的地址。
    • 调用关系错综复杂,难以理清依赖关系。
    • 服务过多,服务状态难以理解,无法根据服务情况动态管理。

    服务治理要做什么?

    • 服务注册中心:实现服务自动注册和发现,无需人为记录服务地址。
    • 服务自动订阅,服务列表自动推送,服务调用透明化,无需关心依赖关系。
    • 动态监控服务状态监控报告,人为控制服务状态。

    缺点:

    • 服务间会有依赖关系,一旦某个环节出错会影响很大。(形成雪崩
    • 服务关系复杂,运维、测试部署困难,不符合DevOps思想。
  2. 微服务架构

    image-20210125102852366

微服务特点:

  • 单一职责:微服务中每一个服务都对应唯一的业务能力,做到单一职责。
  • :微服务的服务拆分粒度很小。例如:一个用户管理就可以作为一个服务。
  • 面向服务:每个服务都要对外暴露Rest风格服务接口API。不关心服务的技术实现,做到与平台和语言无关,不限定技术实现,只提供Rest的接口即可。

1.3、java主流框架演变之路

  1. JSP+Servlet+JavaBean(实体类)
  2. MVC三层架构

model view controller

image-20210105194646063

browser:浏览器,发送http请求,和接收处理完的响应

controller:控制层,接收浏览器发送的请求,交由model层进行处理

model:主要是用来操作数据库,具体是dao层data access object 数据访问对象

view:视图层,前端的东西html,css,js把返回的结果数据集合进行装饰一下,变得好看,再返回给controller,controller返回响应给浏览器

  1. SSH

  2. SSM (spring + SpringMVC + mybatis)

  3. springboot(约定大于配置)

二、Spring官网及版本

1.官网

  https://spring.io/

img

2.版本命名规则

spring版本命名规则

标识 说明 含义
Snapshot 快照版 尚不稳定、处于开发中的版本
Release 稳定版 功能相对稳定,可以对外发行,但有时间限制
GA 正式版 代表广泛可用的稳定版
M 里程碑版 具有一些全新的功能或者是具有里程碑意义的版本
RC 终测版 作为正式版发布

img
img

附:通用命名规则,如 10.0.1

序号 说明
x 表示主版本号(Major),当API的兼容性变化时(参数个数、类型变化,返回值改变等),x递增
y 表示次版本号(Minor ),增加功能时(不影响原有API的兼容性),y递增
z 表示修订号(Patch),修复现有API的bug或优化性能时(不影响API的兼容性),z递增

补充:CURRENT 表示当前最新的版本

官网地址:https://spring.io/projects/spring-framework#overview

压缩包下载地址:https://repo.spring.io/release/org/springframework/spring/

源码地址:https://github.com/spring-projects/spring-framework

3.核心解释

Spring makes it easy to create Java enterprise applications. It provides everything you need to embrace the Java language in an enterprise environment, with support for Groovy and Kotlin as alternative languages on the JVM, and with the flexibility to create many kinds of architectures depending on an application’s needs. As of Spring Framework 5.1, Spring requires JDK 8+ (Java SE 8+) and provides out-of-the-box support for JDK 11 LTS. Java SE 8 update 60 is suggested as the minimum patch release for Java 8, but it is generally recommended to use a recent patch release.

Spring supports a wide range of application scenarios. In a large enterprise, applications often exist for a long time and have to run on a JDK and application server whose upgrade cycle is beyond developer control. Others may run as a single jar with the server embedded, possibly in a cloud environment. Yet others may be standalone applications (such as batch or integration workloads) that do not need a server.

Spring is open source. It has a large and active community that provides continuous feedback based on a diverse range of real-world use cases. This has helped Spring to successfully evolve over a very long time.

Spring 使创建 Java 企业应用程序变得更加容易。它提供了在企业环境中接受 Java 语言所需的一切,,并支持 Groovy 和 Kotlin 作为 JVM 上的替代语言,并可根据应用程序的需要灵活地创建多种体系结构。 从 Spring Framework 5.0 开始,Spring 需要 JDK 8(Java SE 8+),并且已经为 JDK 9 提供了现成的支持。

Spring支持各种应用场景, 在大型企业中, 应用程序通常需要运行很长时间,而且必须运行在 jdk 和应用服务器上,这种场景开发人员无法控制其升级周期。 其他可能作为一个单独的jar嵌入到服务器去运行,也有可能在云环境中。还有一些可能是不需要服务器的独立应用程序(如批处理或集成的工作任务)。

Spring 是开源的。它拥有一个庞大而且活跃的社区,提供不同范围的,真实用户的持续反馈。这也帮助Spring不断地改进,不断发展。
  • spring是一个IOC和AOP的容器框架
    • IOC 控制反转
    • AOP 面向切面编程
    • 容器: 类似装水的桶,只不过这个桶里装的不再是水,而是对象(bean)

三、模块概览

一个大绿框是一个模块,大绿框里的小黑框是所依赖的核心jar包

image-20210105193325579

Aspects要用,上图标错了,Transactions事务也要用

模块解释
Test:Spring的单元测试模块
Core Container:核心容器模块
AOP+Aspects:面向切面编程模块
Instrumentation:提供了class instrumentation支持和类加载器的实现来在特定的应用服务器上使用,几乎不用
Messaging:包括一系列的用来映射消息到方法的注解,几乎不用
Data Access/Integration:数据的获取/整合模块,包括了JDBC,ORM,OXM,JMS和事务模块
Web:提供面向web整合特性

1.核心模块

模块名称 主要功能
spring-core 依赖注入IOC与DI的最基本实现
spring-beans Bean工厂与Bean的装配 。
spring-context 定义基础的Spring的Context上下文,即IOC容器。
spring-context-support 对Spring IOC容器的扩展支持,以及IOC子容器。
spring-context-indexer Spring的类管理组件和ClassPath扫描。
spring-expression Spring表达式语言。spEl

2.切面编程模块

模块名称 主要功能
spring-aop 面向切面编程的应用模块,整合Asm,CGLib,JDKProxy 。
spring-aspects 集成AspectJ,AOP应用框架。
spring-instrument 动态Class Loading模块。

3.数据访问与集成模块

模块名称 主要功能
spring-jdbc Spring 提供的JDBC抽象框架的主要实现模块,用于简化Spring对JDBC的操作。
spring-tx Spring JDBC事务控制实现模块。
spring-orm 主要集成Hibernate,java Persistence API(JPA)和Java Data Objects(JDO)。
spring-oxm 将Java对象映射成XML数据,或将XML数据映射成java对象。
spring-jms Java Message Service能够发送和接收信息。

4.Web模块

模块名称 主要功能
spring-web 提供了最基础的Web支持,主要建立于核心容器之上,通过Servlet或者Listeners来初始化IOC容器。
spring-webmvc 实现了spring MVC(model-view-controller)的Web应用。
spring-websocket 主要是与Web前端的双工通讯协议。
spring-webflux 一个新的非阻塞函数式Reactive Web框架,可以用来建立异步的,非阻塞,事件驱动的服务。

5.通信报文模块

几乎不用

模块名称 主要功能
spring-messaging 从spring4开始新加入的一个模块,主要职责是为spring框架集成一些基础的报文传送应用。

6.测试模块

模块名称 主要功能
spring-test 为测试提供支持

7.兼容模块

模块名称 主要功能
spring-framework-bom bill of Materials.解决Spring不同模块依赖版本不同问题。

8.模块关系图

img

9.Spring各个jar包作用

Spring AOP:Spring的面向切面编程,提供AOP(面向切面编程)的实现
Spring Aspects:Spring提供的对AspectJ框架的整合
Spring Beans:Spring IOC的基础实现,包含访问配置文件、创建和管理bean等。
Spring Context:在基础IOC功能上提供扩展服务,此外还提供许多企业级服务的支持,有邮件服务、任务调度、JNDI定位,EJB集成、远程访问、缓存以及多种视图层框架的支持。
Spring Context Support:Spring context的扩展支持,用于MVC方面。
Spring Core:Spring的核心工具包
Spring expression:Spring表达式语言
Spring Framework Bom:
Spring Instrument:Spring对服务器的代理接口
Spring Instrument Tomcat:Spring对tomcat连接池的集成
Spring JDBC:对JDBC 的简单封装
Spring JMS:为简化jms api的使用而做的简单封装
Spring Messaging:
Spring orm:整合第三方的orm实现,如hibernate,ibatis,jdo以及spring 的jpa实现
Spring oxm:Spring对于object/xml映射的支持,可以让JAVA与XML之间来回切换
Spring test:对JUNIT等测试框架的简单封装
Spring tx:为JDBC、Hibernate、JDO、JPA等提供的一致的声明式和编程式事务管理。
Spring web:包含Web应用开发时,用到Spring框架时所需的核心类,包括自动载入WebApplicationContext特性的类、Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类。
Spring webmvc:包含SpringMVC框架相关的所有类。包含国际化、标签、Theme、视图展现的FreeMarker、JasperReports、 Tiles、Velocity、XSLT相关类。当然,如果你的应用使用了独立的MVC框架,则无需这个JAR文件里的任何类。
Spring webmvc portlet:Spring MVC的增强
Spring websocket:提供 Socket通信, web端的推送功能

四、IOC(控制反转)

4.1、为什么要引入IOC

先看一个小例子:

创建一个普通的java项目,完成下述功能

UserDao.java

public interface UserDao {
   
    public void getUser();
}

UserDaoImpl.java

public class UserDaoImpl  implements UserDao {
   
    @Override
    public void getUser() {
   
        System.out.println("获取用户数据");
    }
}

UserService.java

public interface UserService {
   
    public void getUser();
}

UserServiceImpl.java

public class UserServiceImpl implements UserService {
   

    private UserDao userDao = new UserDaoImpl();

    @Override
    public void getUser() {
   
        userDao.getUser();
    }
}

SpringDemoTest.java

public class SpringDemoTest {
   
    public static void main(String[] args) {
   
       UserService service = new UserServiceImpl();
       service.getUser();
    }
}

在之前的代码编写过程中,我们都是这么完成我们的功能的,但是如果增加一个UserDao的实现类呢?

UserDaoMysqlImpl.java

public class UserDaoMysqlImpl implements UserDao {
   
    @Override
    public void getUser() {
   
        System.out.println("mysql");
    }
}

如果我们想要使用mysql的话,那么就必须要修改UserServiceImpl.java的代码:

public class UserServiceImpl implements UserService {
   

    private UserDao userDao = new UserDaoMysqlImpl();

    @Override
    public void getUser() {
   
        userDao.getUser();
    }
}

但是如果我们再增加一个oracle的类呢?

UserDaoOracleImpl.java

public class UserDaoOracleImpl implements UserDao {
   
    @Override
    public void getUser() {
   
        System.out.println("oracle");
    }
}

此时UserService还是要继续修改,很显然这样的方式已经不适用于我们的需求了,那么怎么解决呢,可以使用如下的方式

UserServiceImpl.java

public class UserServiceImpl implements UserService {
   
    private UserDao userDao;

    //通过set方法来实现想调用UserDao接口的哪个实现类就set哪个实现类
    public void setUserDao(UserDao userDao){
   
        this.userDao = userDao;
    }
    
    @Override
    public void getUser() {
   
        userDao.getUser();
    }
    
}

测试类SpringDemoTest.java

public class SpringDemoTest {
   
    public static void main(String[] args) {
   
        UserServiceImpl userService = new UserServiceImpl();
        //把UserDaoMysql的实现类set进去
        userService.setUserDao(new UserDaoMysqlImpl());
        //set进去来进行调用
        userService.getUser();

        userService.setUserDao(new UserDaoOracleImpl());
        userService.getUser();
    }
}

其实从刚刚的代码中,大家应该能体会解耦的重要性了,下面我们就开始学习Spring的IOC。

IOC叫控制反转

首先需要搞清楚如下几个问题:

1.谁控制谁
2.控制的是什么
3.什么是反转
4.谁/哪些方面被反转

IOC基本概念

官方解释:

IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern.
	IOC与大家熟知的依赖注入同理,. 这是一个通过依赖注入对象的过程 也就是说,它们所使用的对象,是通过构造函数参数,工厂方法的参数或者是从工厂方法的构造函数或返回值的对象实例设置的属性,然后容器在创建bean时注入这些需要的依赖。 这个过程相对普通创建对象的过程是反向的(因此称之为IoC),bean本身通过直接构造类来控制依赖关系的实例化或位置,或提供诸如服务定位器模式之类的机制。

人话:

说大白话就是对象的创建不再需要我们new了,让别人new好,我们直接调用。
举个例子:找女朋友,之前的办法是我们自己找,按照自己的标准,要什么样的,去找,找到了结婚,类似我们的new操作,我们现在不用自己找了,找个中介,婚介所去找,我们给婚介所提出我们所需要的条件(白的,黑的,胖的,瘦的)这些就相当于是属性,让婚介所给我们找好,直接结婚就行。这个中介(婚介所)就相当于是容器

这就是控制反转,不用自己new对象,提出自己的条件(就是类里的属性),类就是我们要找什么东西(比如:女人),由IOC容器创建好,放到容器里,我们直接取就行。

控制反转(IOC)是一种思想

现在回答上面的问题

1.谁控制谁  IOC容器控制对象(bean) (婚介所控制女孩)
2.控制的是什么  对象(bean) (女孩)
3.什么是反转 我们之前都是主动得去new,现在不用了,别人创建好了,我们直接拿,或者说叫被动的接受。 (婚介所帮我们找好)
4.谁/哪些方面被反转  对象的创建不用自己创建了  (女孩不用自己找了)

DI与IOC

DI:依赖注入,利用set方法来进行注入,IOC:控制反转,可以理解为一种思想,两者本质上还是有区别

IOC是一种思想,DI是这种思想的具体实现方式

总结

​ 在此处总结中,希望大家能够能够明白两件事: 解耦 和 生态

1、解耦

​ 在面向对象设计的软件系统中,底层的实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑。

image-20210105223044244

​ 需要注意的是,在这样的组合关系中,一旦某一个对象出现了问题,那么其他对象肯定回有所影响,这就是耦合性太高的缘故,但是对象的耦合关系是无法避免的,也是必要的。随着应用程序越来越庞大,对象的耦合关系可能越来越复杂,经常需要多重依赖关系,因此,无论是架构师还是程序员,在面临这样的场景的时候,都需要减少这些对象的耦合性。

image-20210105223112614

​ 耦合的关系不仅仅是对象与对象之间,也会出现在软件系统的各个模块之间,是我们需要重点解决的问题。而为了解决对象之间的耦合度过高的问题,我们就可以通过IOC来实现对象之间的解耦,spring框架就是IOC理论最最广泛的应用。

image-20210105223135815

​ 从上图中可以看到,当引入了第三方的容器之后,几个对象之间就没有了耦合关系,全部对象都交由容器来控制,这个容器就相当于粘合剂,将系统的对象粘合在一起发挥作用。

2、生态

​ 任何一个语言或者任何一个框架想要立于不败之地,那么很重要的就是它的生态。就是让更多的人用它。

4.2、使用

4.2.1、原始的使用

使用手动加载jar包的方式实现,分为三个步骤,现在几乎不用

  • 手动导入以下五个包

    commons-logging-1.2.jar
    spring-beans-5.2.3.RELEASE.jar
    spring-context-5.2.3.RELEASE.jar
    spring-core-5.2.3.RELEASE.jar
    spring-expression-5.2.3.RELEASE.jar

  • 写配置

    Person.java

    public class Person {
         
        private int id;
        private String name;
        private int age;
        private String gender;
    
        public int getId() {
         
            return id;
        }
    
        public void setId(int id) {
         
            this.id = id;
        }
    
        public String getName() {
         
            return name;
        }
    
        public void setName(String name) {
         
            this.name = name;
        }
    
        public int getAge() {
         
            return age;
        }
    
        public void setAge(int age) {
         
            this.age = age;
        }
    
        public String getGender() {
         
            return gender;
        }
    
        public void setGender(String gender) {
         
            this.gender = gender;
        }
    
        @Override
        public String toString() {
         
            return "Person{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", age=" + age +
                    ", gender='" + gender + '\'' +
                    '}';
        }
    }
    
    

    ioc.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <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">
    
        <!--注册一个对象,spring会自动创建这个对象-->
        <!--
        一个bean标签就表示一个对象
        id:这个对象的唯一标识
        class:注册对象的完全限定名
        -->
        <bean id="person" class="com.king.bean.Person">
            <!--使用property标签给对象的属性赋值
            name:表示属性的名称
            value:表示属性的值
            -->
            <property name="id" value="1"></property>
            <property name="name" value="zhangsan"></property>
            <property name="age" value="18"></property>
            <property name="gender" value=""></property>
        </bean>
    </beans>
    
  • 测试

    SpringDemoTest.java

    //容器中的person对象是什么时候创建的?
    //容器中的对象在容器创建完成之前就已经把对象创建好了
    public class MyTest {
         
        public static void main(String[] args) {
         
            /*
            * applicationContext:表示IOC容器的入口,想要获取对象的话,必须要创建该类
            *   该类有两个读取配置文件的实现类
            *       ClassPathXmlApplicationContext:表示从classpath中读取数据 放的是spring配置文件的位置
            *       FileSystemXmlApplicationContext:表示从当前文件系统读取数据,
            *
            *
            * * */
            ApplicationContext context = new ClassPathXmlApplicationContext("ioc.xml");
            //获取具体的bean实例对象,需要进行强制类型转换
    //        Person person = (Person) context.getBean("person");
            //获取对象的时候不需要强制类型转换
    //        Person person = context.getBean("person", Person.class);
    //        Person person = context.getBean(Person.class); 这种获取bean的方法适合容器中只有一个bean对象,如果有多个相同bean的对象,那么这种方法来获取就会报错
    //        System.out.println(person);
        }
    }
    
    

    容器中的person对象是什么时候创建的?

​ 容器中的对象在容器创建完成之前就已经把对象创建好了

4.2.2、使用maven来创建spring项目

  • 创建maven项目

  • 添加spring-context的依赖

    只需要导入spring-context的核心依赖包即可,因为ClassPathXmlApplicationContext是spring框架的入口,我们只需要导入这个类所属的包,其余所依赖的包会自动导入

    <dependencies>
    <!--        引入context依赖后,spring装配bean的核心包就全部被导进来了,因为context是spring框架的入口-->
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.3.2</version>
            </dependency>
    
    </dependencies>
    
  • 编写一个小demo,例子同上,此处就不再显示了

注意

  • 配置文件需要放在resources包下

总结

  • ApplicationContext是IOC容器的入口(接口),可以通过获取ApplicationContext的实体化对象(容器),来获取实体类对象。
  • 实体类bean什么时候被创建,默认是在IOC容器创建好之前就被创建好了,放在容器中。
  • bean的创建默认是单例的,就是只创建一个对象,谁用谁取,想要修改需要在xml文件中修改属性
  • bean属性值的注入,依赖set方法,所以,在bean中必须编写set方法
  • 对象的属性是由set方法后面的大写字母开头的那个单词决定的,而不是成员变量来决定
解释:property 属性  name的值是由set方法名后面的大写字母开头的单词决定的 例如:setAdddr
<property name="adddr" value="北京"/>

4.3、Spring对象的获取

两种方式

方式一:

通过bean的id来获取IOC容器中的对象

ApplicationContext context = new ClassPathXmlApplicationContext ( "springApplicationo.xml" );
//通过id来获取IOC容器对象,此种方法指明了获取的对象的类型
User user = context.getBean ( "user",User.class );
//这种方式需要进行强制类型转换,没有指明获取对象的类型
User user1 = (User)context.getBean ( "user" );
方式二:

通过bean的类型来获取对象

ApplicationContext context = new ClassPathXmlApplicationContext ( "springApplicationo.xml" );
//直接通过实体类的.class类型来获取对象
User user = context.getBean ( User.class );

但这种方法容易产生问题:

当我们在spring的配置文件中相同的bean注册了多次,例如:

 <bean id="user" class="com.king.pojo.User">
        <property name="age" value="20"/>
        <property name="name" value="胡宗宪"/>
        <property name="adddr" value="北京"/>
    </bean>

    <bean id="user2" class="com.king.pojo.User">
        <property name="age" value="22"/>
        <property name="name" value="嘉靖"/>
        <property name="adddr" value="南京"/>
    </bean>

这时使用第二种方式来获取对象,就会出现问题,context容器不知道该取哪一个,由于有两个属性值完全不同的对象,但类型是相同的,容器不知道如何进行分辨。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hhQTBnrV-1617549428480)(Spring.assets/image-20210106182407023.png)]

(期望找到一个,但是出现了两个)

4.4、属性值注入

1、最常用的属性值的注入方式

通过无参构造方法来创建

<bean id="user" class="com.king.pojo.User">
    <!--这里property标签里的属性 name 指的是set方法名上紧跟着set之后的那部分单词,首字母小写-->
    <property name="age" value="20"/>
    <property name="name" value="胡宗宪"/>
    <property name="adddr" value="北京"/>
</bean>
@Test
public void test(){
   
   ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
   //在执行getBean的时候, user已经创建好了, 通过无参构造
   User user = context.getBean("user",User.class);
   System.out.println(user);
}

2、通过构造器给属性赋值

一定要记得给实体类bean添加构造方法

<!--    通过构造方法来给属性赋值 -->
<bean id="user3" class="com.king.pojo.User">
    <!--   name 填写构造方法中的参数名,而不是实体类中的属性名字  value填写要赋给属性的值-->
    <constructor-arg name="name" value="李斯"></constructor-arg>
    <constructor-arg name="age" value="123"></constructor-arg>
    <constructor-arg name="addr" value="成都"></constructor-arg>
</bean>

<!--    简写:name标签属性可以省略,只要value的值和实体类中的构造方法参数顺序一致,依然可以赋上值-->
<bean id="user3" class="com.king.pojo.User">
    <constructor-arg  value="李斯"></constructor-arg>
    <constructor-arg  value="123"></constructor-arg>
    <constructor-arg  value="成都"></constructor-arg>
</bean>

<!--如果想不按照顺序来添加参数值,那么可以搭配index属性来使用 -->
<bean id="person4" class="com.king.bean.Person">
    <constructor-arg value="lisi" index="1"></constructor-arg>
    <constructor-arg value="1" index="0"></constructor-arg>
    <constructor-arg value="" index="3"></constructor-arg>
    <constructor-arg value="20" index="2"></constructor-arg>
</bean>

<!--当有多个参数个数相同,不同类型的构造器的时候,可以通过type来强制类型-->
    将person的age类型设置为Integer类型
public Person(int id, String name, Integer age) {
    this.id = id;
    this.name = name;
    this.age = age;
    System.out.println("Age");
}

public Person(int id, String name, String gender) {
    this.id = id;
    this.name = name;
    this.gender = gender;
    System.out.println("gender");
}

<bean id="person5" class="com.king.bean.Person">
    <constructor-arg value="1"></constructor-arg>
    <constructor-arg value="lisi"></constructor-arg>
    <constructor-arg value="20" type="java.lang.Integer"></constructor-arg>
</bean>

<!--如果不修改为integer类型,那么需要type跟index组合使用-->
<bean id="person5" class="com.king.bean.Person">
    <constructor-arg value="1"></constructor-arg>
    <constructor-arg value="lisi"></constructor-arg>
    <constructor-arg value="20" type="int" index="2"></constructor-arg>
</bean>

<bean id="user6" class="com.king.pojo.User">
    <constructor-arg value="儒圣"></constructor-arg>
    <constructor-arg value="深圳"></constructor-arg>
    <constructor-arg value="45798" type="java.lang.Integer"></constructor-arg>
    <!--Date类型指定value的时候,用/分开,spring可以自动识别-->
    <constructor-arg value="2021/1/6" type="java.util.Date"></constructor-arg>
</bean>

3、通过命名空间来为bean赋值

3.1、通过p命名空间来注入

User.java :【注意:这里有或没有构造器都不影响p命名空间的注入!】

 public class User {
     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 "User{" +
                 "name='" + name + '\'' +
                 ", age=" + age +
                 '}';
    }
 }

p命名空间的注入需要在头文件中加入约束文件

 导入约束 : xmlns:p="http://www.springframework.org/schema/p"

 <!--P(属性: properties)命名空间 , 直接注入属性-->
 <bean id="user" class="com.pojo.User" p:name="king" p:age="18"/>
3.2、通过c命名空间注入
 导入约束 : xmlns:c="http://www.springframework.org/schema/c"
 <!--C(构造: Constructor)命名空间 , 使用构造器注入-->
 <bean id="user" class="com.pojo.User" c:name="alibab" c:age="18"/>

发现问题:爆红,因为没有有参构造

解决:把有参构造加上就可以解决,这里我们就知道了,c就是所谓的构造器注入

4、为复杂类型进行赋值

要求被注入的属性必须具有set方法,set方法的方法名需要由IDEA编译器自动生成(set+属性首字母大写),如果属性是boolean类型,没有set方法,只有is

测试类pojo类:

Person.java

public class Person {
   
    private String name;
    private Integer age;
    private Boolean gender;
    private String[] hobbies;
    private ArrayList<Book> books;
    private Set<String> set;
    private Address address;
    private HashMap<String, Object> map;
    private Properties pro;


    public String getName ( ) {
   
        return name;
    }

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

    public Integer getAge ( ) {
   
        return age;
    }

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

    public Boolean getGender ( ) {
   
        return gender;
    }

    public void setGender ( Boolean gender ) {
   
        this.gender = gender;
    }

    public String[] getHobbies ( ) {
   
        return hobbies;
    }

    public void setHobbies ( String[] hobbies ) {
   
        this.hobbies = hobbies;
    }


    public void setBooks ( ArrayList<Book> books ) {
   
        this.books = books;
    }

    public Set<String> getSet ( ) {
   
        return set;
    }

    public void setSet ( Set<String> set ) {
   
        this.set = set;
    }

    public Address getAddress ( ) {
   
        return address;
    }

    public void setAddress ( Address address ) {
   
        this.address = address;
    }

    public HashMap<String, Object> getMap ( ) {
   
        return map;
    }

    public void setMap ( HashMap<String, Object> map ) {
   
        this.map = map;
    }

    public Properties getPro ( ) {
   
        return pro;
    }

    public void setPro ( Properties pro ) {
   
        this.pro = pro;
    }

    @Override
    public String toString ( ) {
   
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                ", hobbies=" + Arrays.toString ( hobbies ) +
                ", books=" + books +
                ", set=" + set +
                ", address=" + address +
                ", map=" + map +
                ", pro=" + pro +
                '}';
    }
}

Address.java

public class Address {
   
    private String city;
    private String country;
    private String province;

    public String getCity ( ) {
   
        return city;
    }

    public void setCity ( String city ) {
   
        this.city = city;
    }

    public String getCountry ( ) {
   
        return country;
    }

    public void setCountry ( String country ) {
   
        this.country = country;
    }

    public String getProvince ( ) {
   
        return province;
    }

    public void setProvince ( String province ) {
   
        this.province = province;
    }

    @Override
    public String toString ( ) {
   
        return "Address{" +
                "city='" + city + '\'' +
                ", country='" + country + '\'' +
                ", province='" + province + '\'' +
                '}';
    }
}

Book.java

public class Book {
   
    private String author;
    private String book_name;

    public String getAuthor ( ) {
   
        return author;
    }

    public void setAuthor ( String author ) {
   
        this.author = author;
    }

    public String getBook_name ( ) {
   
        return book_name;
    }

    public void setBook_name ( String book_name ) {
   
        this.book_name = book_name;
    }

    @Override
    public String toString ( ) {
   
        return "Book{" +
                "author='" + author + '\'' +
                ", book_name='" + book_name + '\'' +
                '}';
    }
}

1.常量注入
<property name="name" value="曾国藩"></property>   String
<property name="age" value="100"></property>   Integer
<property name="gender" value="false"></property>  Boolean
2.引用类型注入

三种方式:

<!--        注入引用类型-->
===========================================================
<!--        使用ref属性来引入外部的bean-->
        <property name="address" ref="add"></property>
=========================================================
<!--        和上面的方式一样,只不过换了一种写法-->
         <property name="address">
             <ref bean="add"></ref>
         </property>
====================================================================
        <property name="address">
<!--            使用内部bean标签来注入引用类型 内部bean无法从IOC容器中获取对象-->
            <bean id="add2" class="com.king.pojo.Address">
                <property name="province" value="河北"></property>
                <property name="country" value="日本"/>
                <property name="city" value="洛杉矶"/>
            </bean>
        </property>
3.数组的注入
<!--        注入数组类型-->
<!--        <property name="hobbies" value="篮球,羽毛球,足球"></property>-->
        <property name="hobbies">
            <array>
                <value>篮球</value>
                <value>足球</value>
                <value>羽毛球</value>
            </array>
        </property>
4.List的注入
<!--        List类型注入-->
        <property name="books">
            <list>
<!--                引入外部的bean-->
                <ref bean="book"></ref>
<!--                创建内部bean-->
                <bean class="com.king.pojo.Book">
                    <property name="author" value="king"/>
                    <property name="book_name" value="阿里巴巴"/>
                </bean>
                <bean id="b2" class="com.king.pojo.Book">
                    <property name="book_name" value="武汉"/>
                    <property name="author" value="中国"/>
                </bean>
            </list>
        </property>
5.set注入

这里虽然写了三个相同的value,但是还是要遵守set的特点,有序不可重复

<!--        set注入-->
        <property name="set">
            <set>
                <value>king</value>
                <value>king</value>
                <value>king</value>
                <value>joye</value>
            </set>
        </property>
6.map注入
<!--        map注入-->
<property name="map">
    <map>
        <entry>
            <key>
                <value>1</value>
            </key>
            <value></value>
        </entry>

        <entry key="2" value=""/>

        <entry key="book" value-ref="book"/>

        <entry key="list">
            <list>
                <bean class="com.king.pojo.Address">
                    <property name="city" value="日本"></property>
                    <property name="country" value="韩国"/>
                    <property name="province" value="山西"/>
                </bean>
                <value>足球</value>
                <ref bean="book"></ref>
            </list>
        </entry>

        <entry key="add">
            <bean class="com.king.pojo.Address">
                <property name="province" value="美国"/>
                <property name="country" value="加拿大"/>
                <property name="city" value="西安"/>
            </bean>
        </entry>
    </map>
</property>
7.properties注入
<property name="pro">
    <props>
        <prop key="a">asd</prop>
        <prop key="b">asdasd</prop>
        <prop key="c">asfdsad</prop>
    </props>
</property>

4.5、继承关系bean的配置

ioc.xml

<!--    继承关系bean的配置-->
        <bean id="user" class="com.king.pojo.User">
            <property name="age" value="20"/>
            <property name="name" value="胡宗宪"/>
            <property name="adddr" value="北京"/>
            <property name="date" value="2022/12/5"/>
        </bean>

<!--parent属性可以指定该bean的属性继承自哪个bean,换句话说,就是获取父类bean中的一些属性值-->
        <bean id="user1" class="com.king.pojo.User" parent="user">
            <property name="age" value="946546"/>
        </bean>

结果

User被创建
User被创建
User{
   age=946546, name='胡宗宪', addr='北京', date=Mon Dec 05 00:00:00 CST 2022}

初始化了两个bean实体类

如果想实现Java文件的抽象类,不需要将当前bean实例化的话,可以使用abstract属性

<!--    继承关系bean的配置  abstract属性可以设置不让这个bean被初始化-->
        <bean id="user" class="com.king.pojo.User" abstract="true">
            <property name="age" value="20"/>
            <property name="name" value="胡宗宪"/>
            <property name="adddr" value="北京"/>
            <property name="da
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蚂蚁爱学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值