【Java框架】Spring框架(一)——Spring基本核心(IOC/DI)

目录

  • Java企业级框架
    • 企业级系统
    • EJB概念解析
    • EJB与Spring的恩怨情仇
  • Spring系统架构
    • 1. Data Access/Integration(数据访问/集成)
    • 2. Web 模块
    • 3. Core Container(Spring 的核心容器)
    • 4. AOP、Aspects、Instrumentation 和 Messaging
    • 5. Test 模块
    • Spring的优点
  • Spring的本质
  • Spring的核心概念
    • 控制反转 / 依赖注入(IOC/DI)
      • IOC 控制反转
      • DI 依赖注入
      • 代码实现
        • 1.依赖
        • 2.java类
        • 3.编写spring配置文件
        • 4.测试
      • IoC 的工作原理
    • Spring Bean定义
    • Spring Bean属性注入
      • setter 注入
        • 代码示例
      • 构造注入
        • 代码示例
      • 构造注入与设置注入的区别
      • P命名空间注入
        • 代码示例
      • 注入不同数据类型
      • 注解注入(使用注解实现IoC)
        • 使用@Autowired注解实现Bean的自动装配,默认按类型匹配,可以使用@Qualifier指定Bean的名称
          • 代码实现
        • 使用Java标准注解完成装配
          • 代码实现
        • 面试题:@Autowired和@Resource之间的异同?
          • 相同点:
          • 不同点:
          • @Resource装配顺序

Java企业级框架

企业级系统

  • 大规模:用户数量多、数据规模大、功能众多
  • 性能和安全要求高
  • 业务复杂
  • 灵活应变

Java技术如何应对?
在这里插入图片描述

EJB概念解析

  • EJB是sun的JavaEE服务器端组件模型,设计目标与核心应用是部署分布式应用程序。简单来说就是把已经编写好的程序(即:类)打包放在服务器上执行。凭借Java跨平台的优势,用EJB技术部署的分布式系统可以不限于特定的平台。
  • EJB (Enterprise JavaBean)是JavaEE的一部分,定义了一个用于开发基于组件的企业多重应用程序的标准。其特点包括网络服务支持和核心开发工具(SDK)。
  • 在JavaEE中,Enterprise Java Beans(EJB)称为Java 企业Bean,是Java的核心代码,分别是会话Bean(Session Bean),实体Bean(Entity Bean)和消息驱动Bean(MessageDriven Bean)。在EJB3.0推出以后,实体Bean被单独分了出来,形成了新的规范JPA。
  • EJB 的设计理念是要做一个最大最全最完善的框架,可惜在现实世界中,我们真正需要的不是这样高大全的笨重武器,而是根据自己需求量身定做的轻型武器。
    屠龙刀虽好,只惜太沉,必然降低轻功,同理一个all in one的框架必然有其负面影响,最明显的就是结构的复杂和效率的低下。
  • 此外对于中小型的应用项目而言,基本不采用分布式的解决方案,那么为什么要采取一个为分布式设计的方案来解决非分布式的问题呢? Spring就是为了解决这个问题而诞生的。

EJB与Spring的恩怨情仇

  • Spring之父为EJB脱去Remote这层皮、将大多数应用中不必要的技术隔离、改造。从适用范围上来说,Spring对EJB做了90%的补充。
  • 可以说,曾经摔的灰头土脸的EJB,下了很大的功夫改头换面脱胎换骨,重新做人了,成为JavaEE框架的标准。
  • 纵观人类历史,官方过于强势,则必然官逼民反;而民间力量过于强大,社会必将不稳定,这都是我们不愿看到的,在技术世界里也一样。对于EJB3 和Spring这两种方案,Spring现在处于压倒性的优势一方,希望EJB3的出现,一来能为官方挽回一些失去的领地,二来也能继续引发更多的探讨,不再拘束于一家之言,只有百家争鸣的环境,才能让开发人员和架构人员对企业应用的构建认识得更加完善,所以最好的方式是EJB3和Spring互相促进,和谐发展。

Spring系统架构

在这里插入图片描述

  • Core Container:核心容器
  • AOP:面向切面编程
  • Aspects:AOP思想实现
  • Data Access:数据访问
  • Data Integration:数据集成
  • Transaction:事务
  • Web:Web开发
  • Test:单元测试与集成测试

1. Data Access/Integration(数据访问/集成)

数据访问/集成层包括 JDBC、ORM、OXM、JMS 和 Transactions 模块,具体介绍如下。

  • JDBC 模块:提供了一个 JBDC 的样例模板,使用这些模板能消除传统冗长的 JDBC 编码还有必须的事务控制,而且能享受到 Spring 管理事务的好处。
  • ORM 模块:提供与流行的“对象-关系”映射框架无缝集成的 API,包括 JPA、JDO、Hibernate 和 MyBatis 等。而且还可以使用 Spring 事务管理,无需额外控制事务。
  • OXM 模块:提供了一个支持 Object /XML 映射的抽象层实现,如 JAXB、Castor、XMLBeans、JiBX 和 XStream。将 Java 对象映射成 XML 数据,或者将XML 数据映射成 Java 对象。
  • JMS 模块:指 Java 消息服务,提供一套 “消息生产者、消息消费者”模板用于更加简单的使用 JMS,JMS 用于用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
  • Transactions 事务模块:支持编程和声明式事务管理。

2. Web 模块

Spring 的 Web 层包括 Web、Servlet、WebSocket 和 Portlet 组件,具体介绍如下。

  • Web 模块:提供了基本的 Web 开发集成特性,例如多文件上传功能、使用的 Servlet 监听器的 IOC 容器初始化以及 Web 应用上下文。
  • Servlet 模块:提供了一个 Spring MVC Web 框架实现。Spring MVC 框架提供了基于注解的请求资源注入、更简单的数据绑定、数据验证等及一套非常易用的 JSP 标签,完全无缝与 Spring 其他技术协作。
  • WebSocket 模块:提供了简单的接口,用户只要实现响应的接口就可以快速的搭建 WebSocket Server,从而实现双向通讯。
  • Portlet 模块:提供了在 Portlet 环境中使用 MVC 实现,类似 Web-Servlet 模块的功能。

3. Core Container(Spring 的核心容器)

Spring 的核心容器是其他模块建立的基础,由 Beans 模块、Core 核心模块、Context 上下文模块和 SpEL 表达式语言模块组成,没有这些核心容器,也不可能有 AOP、Web 等上层的功能。具体介绍如下。

  • Beans 模块:提供了框架的基础部分,包括控制反转和依赖注入。
  • Core 核心模块:封装了 Spring 框架的底层部分,包括资源访问、类型转换及一些常用工具类。
  • Context 上下文模块:建立在 Core 和 Beans 模块的基础之上,集成 Beans 模块功能并添加资源绑定、数据验证、国际化、Java EE 支持、容器生命周期、事件传播等。ApplicationContext 接口是上下文模块的焦点。
  • SpEL 模块:提供了强大的表达式语言支持,支持访问和修改属性值,方法调用,支持访问及修改数组、容器和索引器,命名变量,支持算数和逻辑运算,支持从 Spring 容器获取 Bean,它也支持列表投影、选择和一般的列表聚合等。

4. AOP、Aspects、Instrumentation 和 Messaging

在 Core Container 之上是 AOP、Aspects 等模块,具体介绍如下:

  • AOP 模块:提供了面向切面编程实现,提供比如日志记录、权限控制、性能统计等通用功能和业务逻辑分离的技术,并且能动态的把这些功能添加到需要的代码中,这样各司其职,降低业务逻辑和通用功能的耦合。
  • Aspects 模块:提供与 AspectJ 的集成,是一个功能强大且成熟的面向切面编程(AOP)框架。
  • Instrumentation 模块:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用。
  • messaging 模块:Spring 4.0 以后新增了消息(Spring-messaging)模块,该模块提供了对消息传递体系结构和协议的支持。

5. Test 模块

  • Test 模块:Spring 支持 Junit 和 TestNG 测试框架,而且还额外提供了一些基于 Spring 的测试功能,比如在测试 Web 框架时,模拟 Http 请求的功能。

在这里插入图片描述

Spring的优点

  • 低侵入式设计
  • 独立于各种应用服务器
  • 依赖注入特性将组件关系透明化,降低了耦合度
  • 面向切面编程特性允许将通用任务进行集中式处理
  • 与第三方框架的良好整合

Spring的本质

  • 本质其实就是完全解耦,用户通过容器来接受他们想要的类。

  • 就像我们把一些类放入到一个自动售卖机,我们需要什么类就从里面拿,而不是自己去new

  • 我们可以把类放在一个类似于set的这种结构和有客户new的结构里面,我们称这两种结构的总和叫做容器。

  • 也就是说我们可以通过容器来得到普通类,和有依赖关系的类,那么这些由容器创建的类叫做Bean。

  • 而这个解耦的技术叫做IOC,依赖反转技术。

  • 而用容器创建有依赖关系的类又叫做DI,也就是依赖注入。

  • 那么一下就出现了这几个名词,DI,IOC,bean,容器。

Spring的核心概念

  • IOC :使用对象时,由主动new产生对象转换为由外部提供对象,对象的创建控制权由程序转移到外部,这种思想称为控制反转。就是解耦。

  • IOC容器 :(Core Container)Spring提供了这个容器,用来充当IOC思想中的”外部“。

  • Bean :IOC容器负责对象的创建,初始化等一系列工作,被创建或被管理的对象在IOC容器中统称为bean。

  • DI :在容器中建立bean与bean之间的依赖关系的整个过程,就称为依赖注入。

控制反转 / 依赖注入(IOC/DI)

  • 将组件对象的控制权从代码本身转移到外部容器
    • 组件化的思想:分离关注点,使用接口,不再关注实现
    • 依赖的注入:将组件的构建和使用分开

IOC 控制反转

  • IoC (Inversion of Control) : 控制反转, 是一个理论,概念,思想。把对象的创建,赋值,管理工作都交给代码之外的容器实现, 也就是对象的创建是有其它外部资源完成,这样做实现了与解耦合。
  • 正转:对象的创建、赋值等操作交由程序员手动完成,即使用类似new Xxx(Xxx Xxx)、Xxx.setXxx()语句完成对象的创建与赋值,缺点是一旦程序功能发生改变,涉及到的类就要修改代理,耦合度高,不便于维护和管理。
  • 反转:对象的创建、赋值等操作交由代码之外的容器实现,有容器代替程序员完成对象的创建、赋值;且当程序功能发生变化时,只需要修改容器的配置文件即可。

DI 依赖注入

  • DI(Dependency Injection) :依赖注入, 只需要在程序中提供要使用的对象名称就可以, 至于对象如何在容器中创建, 赋值,查找都由容器内部实现。
    DI是ioc技术的实现方式(即容器如何创建对象这一问题的实现方式)
    在这里插入图片描述

代码实现

1.依赖
	<!-- spring -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.1.9.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.1.9.RELEASE</version>
    </dependency>
2.java类
package com.kgc;

/**
 * @author: zjl
 * @datetime: 2024/3/28
 * @desc:
 */
public class HelloSpring {
    private String who;

    public void show(){
        System.out.println("Hello "+who+"!!!");
    }

    public void setWho(String who){
        this.who = who;
    }
}
3.编写spring配置文件
  • applicationContext.xml
  • 通过spring配置来创建对象(bean),而不再是手动new
<?xml version="1.0" encoding="UTF-8"?>
<beans  xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    ">
    <bean id="hello" class="com.kgc.HelloSpring">
        <!-- setter注入(设置注入) -->
        <property name="who" value="Spring"></property>
    </bean>
</beans>
4.测试

hello对象不是通过new HelloSpring()创建来的,而是从容器中拿的,就像是从spring配置文件中拿的

ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext.xml");
HelloSpring hello = act.getBean("hello",HelloSpring.class);
//hello.setWho("Spring");
hello.show();

IoC 的工作原理

  • 在 Java 软件开发过程中,系统中的各个对象之间、各个模块之间、软件系统和硬件系统之间,或多或少都存在一定的耦合关系。

  • 若一个系统的耦合度过高,那么就会造成难以维护的问题,但完全没有耦合的代码几乎无法完成任何工作,这是由于几乎所有的功能都需要代码之间相互协作、相互依赖才能完成。因此我们在程序设计时,所秉承的思想一般都是在不影响系统功能的前提下,最大限度的降低耦合度。

  • IoC 底层通过工厂模式、Java 的反射机制、XML 解析等技术,将代码的耦合度降低到最低限度,其主要步骤如下。

    • 在配置文件(例如 Bean.xml)中,对各个对象以及它们之间的依赖关系进行配置;
    • 我们可以把 IoC 容器当做一个工厂,这个工厂的产品就是 Spring Bean;
    • 容器启动时会加载并解析这些配置文件,得到对象的基本信息以及它们之间的依赖关系;
    • IoC 利用 Java 的反射机制,根据类名生成相应的对象(即 Spring Bean),并根据依赖关系将这个对象注入到依赖它的对象中。
  • 由于对象的基本信息、对象之间的依赖关系都是在配置文件中定义的,并没有在代码中紧密耦合,因此即使对象发生改变,我们也只需要在配置文件中进行修改即可,而无须对 Java 代码进行修改,这就是 Spring IoC 实现解耦的原理。

Spring Bean定义

  • 由 Spring IoC 容器管理的对象称为 Bean,Bean 根据 Spring 配置文件中的信息创建。
  • 我们可以把 Spring IoC 容器看作是一个大工厂,Bean 相当于工厂的产品。如果希望这个大工厂生产和管理 Bean,就需要告诉容器需要哪些 Bean,以哪种方式装配。
  • Spring 配置文件支持两种格式,即 XML 文件格式和 Properties 文件格式。
    • Properties 配置文件主要以 key-value 键值对的形式存在,只能赋值,不能进行其他操作,适用于简单的属性配置。
    • XML 配置文件采用树形结构,结构清晰,相较于 Properties 文件更加灵活。但是 XML 配置比较繁琐,适用于大型的复杂的项目。
  • 通常情况下,Spring 的配置文件都是使用 XML 格式的。XML 配置文件的根元素是 <beans>,该元素包含了多个子元素 <bean>。每一个 <bean> 元素都定义了一个 Bean,并描述了该 Bean 是如何被装配到 Spring 容器中的。
  • 在 XML 配置的 <beans> 元素中可以包含多个属性或子元素,常用的属性或子元素如下表所示:
属性名称描述
idBean 的唯一标识符,Spring IoC 容器对 Bean 的配置和管理都通过该属性完成。id 的值必须以字母开始,可以使用字母、数字、下划线等符号。
name该属性表示 Bean 的名称,我们可以通过 name 属性为同一个 Bean 同时指定多个名称,每个名称之间用逗号或分号隔开。Spring 容器可以通过 name 属性配置和管理容器中的 Bean。
class该属性指定了 Bean 的具体实现类,它必须是一个完整的类名,即类的全限定名。
scope表示 Bean 的作用域,属性值可以为 singleton(单例)、prototype(原型)、request、session 和 global Session。默认值是 singleton。
constructor-arg<bean> 元素的子元素,我们可以通过该元素,将构造参数传入,以实现 Bean 的实例化。该元素的 index 属性指定构造参数的序号(从 0 开始),type 属性指定构造参数的类型。
property<bean>元素的子元素,用于调用 Bean 实例中的 setter 方法对属性进行赋值,从而完成属性的注入。该元素的 name 属性用于指定 Bean 实例中相应的属性名。
ref<property> 和 等元素的子元索,用于指定对某个 Bean 实例的引用,即 元素中的 id 或 name 属性。
value<property> 和 等元素的子元素,用于直接指定一个常量值。
list用于封装 List 或数组类型的属性注入。
set用于封装 Set 类型的属性注入。
map用于封装 Map 类型的属性注入。
entry<map> 元素的子元素,用于设置一个键值对。其 key 属性指定字符串类型的键值,ref 或 value 子元素指定其值。
init-method容器加载 Bean 时调用该方法,类似于 Servlet 中的 init() 方法
destroy-method容器删除 Bean 时调用该方法,类似于 Servlet 中的 destroy() 方法。该方法只在 scope=singleton 时有效
lazy-init懒加载,值为 true,容器在首次请求时才会创建 Bean 实例;值为 false,容器在启动时创建 Bean 实例。该方法只在 scope=singleton 时有效

Spring Bean属性注入

  • 所谓 Bean 属性注入,简单点说就是将属性注入到 Bean 中的过程,而这属性既可以普通属性,也可以是一个对象(Bean)。
  • Spring 主要通过以下 2 种方式实现属性注入:
    • 构造函数注入
    • setter 注入(又称设值注入)
  • 除了上述两种注入之外还有p命名空间注入(也是依赖与setter注入),和注解注入(最常用,也是最方便)

setter 注入

  • 我们可以通过 Bean 的 setter 方法,将属性值注入到 Bean 的属性中。
  • 在 Spring 实例化 Bean 的过程中,IoC 容器首先会调用默认的构造方法(无参构造方法)实例化 Bean(Java 对象),然后通过 Java 的反射机制调用这个 Bean 的 setXxx() 方法,将属性值注入到 Bean 中。
  • 使用 setter 注入的方式进行属性注入,大致步骤如下:
    • 在 Bean 中提供一个默认的无参构造函数(在没有其他带参构造函数的情况下,可省略),并为所有需要注入的属性提供一个 setXxx() 方法;
    • 在 Spring 的 XML 配置文件中,使用 <beans> 及其子元素 <bean> 对 Bean 进行定义;
    • 在 <bean> 元素内使用 <property> 元素对各个属性进行赋值。
代码示例

package com.kgc;

/**
 * @author: zjl
 * @datetime: 2024/3/28
 * @desc:
 */
public class Person {
    private String name;
    private String words;
    public void say(){
        System.out.println(name+"说:"+words);
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setWords(String words) {
        this.words = words;
    }
}

配置

    <bean id="zhangga" class="com.kgc.Person">
        <property name="name" value="嘎子"></property>
        <property name="words" value="卖酒"></property>
    </bean>
    <bean id="panzi" class="com.kgc.Person">
        <property name="name" value="潘子"></property>
        <property name="words" value="这一行的水太深,你把握不住,让叔来把握"></property>
    </bean>

构造注入

  • 我们可以通过 Bean 的带参构造函数,以实现 Bean 的属性注入。
  • 使用构造函数实现属性注入大致步骤如下:
    • 在 Bean 中添加一个有参构造函数,构造函数内的每一个参数代表一个需要注入的属性;
    • 在 Spring 的 XML 配置文件中,通过 <beans> 及其子元素 <bean> 对 Bean 进行定义;
    • 在 <bean> 元素内使用 <constructor-arg> 元素,对构造函数内的属性进行赋值,Bean 的构造函数内有多少参数,就需要使用多少个 <constructor-arg> 元素。
代码示例

package com.kgc;

/**
 * @author: zjl
 * @datetime: 2024/3/28
 * @desc:
 */
public class Person {
    private String name;
    private String words;
    public void say(){
        System.out.println(name+"说:"+words);
    }

    public Person(String name, String words) {
        this.name = name;
        this.words = words;
    }
}

配置

    <bean id="zhangga" class="com.kgc.Person">
        <constructor-arg name="name" value="嘎子"/>
        <constructor-arg name="words" value="卖酒"/>
    </bean>
    <bean id="panzi" class="com.kgc.Person">
        <constructor-arg name="name" value="潘子"/>
        <constructor-arg name="words" value="这一行的水太深,你把握不住,让叔来把握"/>
    </bean>

构造注入也能通过类型和参数索引进行注入,但是不太方便,了解即可

构造注入与设置注入的区别

构造注入设置注入
通过构造方法实现通过setter访问器实现
灵活性差,仅靠重载限制太多灵活性好,但setter方法数量较多
时效性好时效性差
通过匹配的构造方法实例化,但建议保留无参构造通过无参构造实例化

P命名空间注入

p 命名空间的特点:使用属性而不是子元素的形式配置Bean的属性,从而简化了配置代码

  • 对于直接量(基本数据类型、字符串)属性:p:属性名=“属性值”
  • 对于引用Bean的属性:p:属性名-ref=“Bean的id”

需要先把这句加进去:xmlns:p=“http://www.springframework.org/schema/p”
在这里插入图片描述

代码示例

package com.kgc;

/**
 * @author: zjl
 * @datetime: 2024/3/29
 * @desc:
 */
public class Student {
    private int id;
    private String stuName;
    private String address;
    private School school;

    public void setSchool(School school) {
        this.school = school;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

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

配置

    <bean id="student" class="com.kgc.Student" p:id="1001" p:stuName="张三" p:address="北京" p:school-ref="school">
    </bean>

注入不同数据类型

package com.kgc;

import java.util.*;

/**
 * @author: zjl
 * @datetime: 2024/3/29
 * @desc:
 */
public class MyBean {
    private School school;
    private List<String> list;
    private Set<String> set;
    private Map<String, Object> map;
    private Properties properties;
    private String[] strs;

    @Override
    public String toString() {
        return "MyBean{" +
                "school=" + school +
                ", list=" + list +
                ", set=" + set +
                ", map=" + map +
                ", properties=" + properties +
                ", strs=" + Arrays.toString(strs) +
                '}';
    }

    public void setSchool(School school) {
        this.school = school;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

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

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

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    public void setStrs(String[] strs) {
        this.strs = strs;
    }
}

配置

    <bean id="myBean" class="com.kgc.MyBean">
        <property name="school">
            <bean class="com.kgc.School">
                <constructor-arg name="schoolName" value="XTXG"/>
            </bean>
        </property>
        <property name="list">
            <list>
                <value>1</value>
                <value>2</value>
                <value>3</value>
            </list>
        </property>
        <property name="set">
            <set>
                <value>aaa</value>
                <value>bbb</value>
                <value>aaa</value>
            </set>
        </property>
        <property name="map">
            <map>
                <entry key="aaa" value="111"></entry>
                <entry key="bbb" value="222"></entry>
                <entry key="ccc" value="111"></entry>
            </map>
        </property>
        <property name="properties">
            <props>
                <prop key="A">aaa</prop>
                <prop key="B">bbb</prop>
                <prop key="driver">com.mysql.jdbc.Driver</prop>
            </props>
        </property>
        <property name="strs">
            <array>
                <value>z</value>
                <value>y</value>
                <value>x</value>
            </array>
        </property>
    </bean>

注解注入(使用注解实现IoC)

注解方式将Bean的定义信息和Bean实现类结合在一起,Spring提供的注解有

  • @Component:实现Bean组件的定义
  • @Repository :用于标注DAO类
  • @Service :用于标注业务类
  • @Controller :用于标注控制器类
使用@Autowired注解实现Bean的自动装配,默认按类型匹配,可以使用@Qualifier指定Bean的名称
代码实现

@Service("userService") 
public class UserServiceImpl implements UserService { 
        @Autowired
        @Qualifier("userDao")
        private UserDao dao; 
               …… 
}
@Service("userService") 
public class UserServiceImpl implements UserService { 
        private UserDao dao;
        @Autowired
        public void setDao((@Qualifier("userDao") UserDao dao) {
                 this.dao = dao;
        } 
  …… 
}

配置
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<beans  xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.2.xsd
    ">
    <!--<context:component-scan base-package="com.zjl.service,com.zjl.mapper,com.zjl.controller"/>-->
    <!-- base-package: 指定要扫描的包,
    spring容器会自动扫描该包下的所有类,并根据注解自动注册为bean -->
    <context:component-scan base-package="com.zjl"/>
</beans>
使用Java标准注解完成装配

使用@Resource注解实现组件装配,默认按名称匹配

代码实现

配置不变,类基本不变,就是注解使用上换成@Resource

@Service("userService") 
public class UserServiceImpl implements UserService { 
	@Resource(name = "userDao")
	private UserDao dao; 
	…… 
}
@Service("userService") 
public class UserServiceImpl implements UserService { 
	@Resource
	private UserDao dao; 
	…… 
}
面试题:@Autowired和@Resource之间的异同?
相同点:

@Resource的作用相当于@Autowired,均可标注在字段或属性的setter方法上。

不同点:
  1. 提供方:@Autowired是由Spring提供;@Resource是由javax.annotation.Resource提供,即J2EE提供,需要JDK1.6及以上。
  2. 注入方式:@Autowired只按照byType 注入;@Resource默认按byName自动注入,也提供按照byType 注入;
  3. 属性:@Autowired按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。@Resource有两个中重要的属性:name和type。name属性指定byName,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。需要注意的是,@Resource如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时, @Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了。
@Resource装配顺序
  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

推荐使用@Resource注解在字段上,这样就不用写setter方法了.并且这个注解是属于J2EE的,减少了与Spring的耦合,这样代码看起就比较优雅 。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/561936.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

冰达ROS机器人快速使用指南

欢迎来到《冰达ROS机器人极简使用指南》 Q&#xff1a;这份教程适合谁&#xff1f; A&#xff1a;适合完全0基础新手&#xff0c;需要快速跑起来机器人的基本功能。也适合技术大佬需要快速的了解冰达ROS机器人的使用方法。 Q&#xff1a;这份教程内容很少&#xff0c;是不是…

迅雷下载不了的资源怎么下载?

我想下载Boost库&#xff0c;但是下载不下来 用迅雷下载是一直卡在0k 后来尝试在centos上用wget进行下载&#xff0c;竟然可以 wget https://boostorg.jfrog.io/artifactory/main/release/1.85.0/source/boost_1_85_0.tar.gz

信息打点--语言框架

指纹识别 后端 CMS:一般php开发居多源码程序&#xff0c;其他语言也存在&#xff0c;但不易识别&#xff08;利用源码程序名去搜漏洞情况&#xff0c;源码下载进行后期的代码审计&#xff09; 前端 js框架&#xff08;爬取更多的js从里面筛选URL或敏感泄露key&#xff09;等…

docker-compose 安装MongoDB续:创建用户及赋权

文章目录 1. 问题描述2. 分析2.1 admin2.2 config2.3 local 3. 如何连接3.解决 1. 问题描述 在这一篇使用docker-compose创建MongoDB环境的笔记里&#xff0c;我们创建了数据库&#xff0c;但是似乎没有办法使用如Robo 3T这样的工具去连接数据库。连接的时候会返回这样的错误&…

C++参考手册使用说明

C参考手册使用说明 文章目录 C参考手册使用说明1 为什么要使用C参考手册2 网站3 C参考手册离线格式4 C参考手册使用说明1.1 离线C参考手册下载1.2 html离线C参考手册1.3 chm离线C参考手册1.4 linux安装包C参考手册&#xff08;只有英文版本&#xff09;1.5 qch离线C参考手册 更…

2 逻辑斯蒂回归(分类)

目录 1 理论 逻辑回归假设数据服从伯努利分布&#xff08;二分类&#xff09;,通过极大化似然函数的方法&#xff0c;运用梯度下降来求解参数&#xff0c;来达到将数据二分类的目的。 逻辑斯蒂回归&#xff08;Logistic Regression&#xff09;是一种用于解决分类问题的…

MySQL下载与安装

文章目录 1&#xff1a;MySQL下载与安装2&#xff1a;配置环境变量3&#xff1a;验证是否安装成功 1&#xff1a;MySQL下载与安装 打开MySQL官网&#xff0c;MySQL 下载链接选择合适的版本和操作系统&#xff0c;页面跳转之后选择No thanks, just start my download.等待下载即…

seatable部署之后network error【seatable】

这里写自定义目录标题 问题汇总 问题汇总 seatable服务部署后&#xff0c;组件显示正常运行&#xff0c;创建表单&#xff0c;显示Network error 点击错误信息&#xff0c;查看其跳转至另一个页面

详解JVM类加载

从类被加载到虚拟机内存中开始&#xff0c;到释放内存总共有7个步骤&#xff1a;加载&#xff08;Loading&#xff09;、验证&#xff08;Verification&#xff09;、准备&#xff08;Preparation&#xff09;、解析&#xff08;Resolution&#xff09;、初始化&#xff08;Ini…

Jenkins构建实用场景指南

1 总体说明 本文主要介绍在研发实战时,通过Jenkins解决企业级软件构建打包一些实用场景。通常是在打包构建前,通过命令和工具进行预处理,避免修改源码,可按需配置构建任务,自动持续集成。 2 Jenkins简介 2.1 复制任务 研发实战创建构建任务,推荐从已有的构建任务进行…

项目管理-项目成本管理

目录 一、成本管理概述 二、成本估算 2.1 定义 2.2 成本估算方法 2.2.1 自顶向下的估算 2.2.1.1 估算方法 2.2.1.2 优点 2.2.1.3 缺点 2.2.2 自底向上的估算 2.2.2.1 估算方法 2.2.2.2 优点 2.2.2.3 缺点 2.2.3 差别估算法 三、成本预算 3.1 定义 3.2 成本预算的…

vue+springboot+mybatis-plus改装

①添加依赖 <!-- mybatis-plus --> <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.2</version> </dependency> pom.xml: <?xml version"…

springboot+java照相馆预约管理系统ssm

框架&#xff1a;ssm/springboot都有 jdk版本&#xff1a;1.8 及以上 ide工具&#xff1a;IDEA 或者eclipse 数据库: mysql 编程语言: java 前端&#xff1a;layuibootstrapjsp 详细技术&#xff1a;HTMLCSSJSjspspringmvcmybatisMYSQLMAVENtomcat 开发工具 IntelliJ IDEA: 一…

Oracle解析exp、imp及常见的问题

前言 在工作中经常需要不同数据库的导入和导出。exp和imp可以实现数据的迁移。 exo会转储产生对应的二进制文件,里面包括数据的定义信息、数据内容等,即为dump文件。 下面是使用exp和imp的一些场景 exp和imp主要有4中模式: 1)数据库模式 数据库模式也就是我们说的全备…

五分钟手撕“三大特性”<继承>(下)

目录 一、protected 关键字 二、继承方式 三、final 关键字 四、子类的构造方法 五、this和super &#xff08;一&#xff09;相同点&#xff1a; &#xff08;二&#xff09;不同点&#xff1a; 六、代码块的执行先后 一、protected 关键字 在类与对象中提到过&…

二维码门楼牌管理应用平台建设:网格化管理的新篇章

文章目录 前言一、二维码门楼牌管理应用平台的建设背景二、二维码门楼牌管理应用平台的功能特点三、二维码门楼牌管理应用平台的实际应用四、二维码门楼牌管理应用平台的前景展望 前言 随着信息技术的飞速发展&#xff0c;二维码门楼牌管理应用平台的建设已成为城市网格化管理…

第十四届蓝桥杯省赛C/C++大学B组真题-飞机降落

思路&#xff1a;根据数据范围N<10猜测用DFS剪枝&#xff0c;因为菜狗不会状压dp。根据题目&#xff0c;一般这种飞机的题都会用到贪心的思想。思想是每架飞机都要卡极限最早降落时间&#xff0c;从而保证后面的飞机能够有充足时间降落。 代码参考博客MQy大佬有详细解答 #i…

IDEA中添加servlet模板

官方代码链接 #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end #parse("File Header.java")import javax.servlet.*; import javax.servlet.http.*;

Java面试八股文(JVM篇)(❤❤)

Java面试八股文_JVM篇 1、知识点汇总2、知识点详解&#xff1a;3、说说类加载与卸载11、说说Java对象创建过程12、知道类的生命周期吗&#xff1f;14、如何判断对象可以被回收&#xff1f;17、调优命令有哪些&#xff1f;18、常见调优工具有哪些20、你知道哪些JVM性能调优参数&…

统计大写辅音字母

题目&#xff1a; 英文辅音字母是除A、E、I、O、U以外的字母。本题要求编写程序&#xff0c;统计给定字符串中大写辅音字母的个数。 输入格式&#xff1a; 输入在一行中给出一个不超过80个字符、并以回车结束的字符串。 输出格式&#xff1a; 输出在一行中给出字符串中大写…