商品网站源码,个人品牌网站设计,网页素材下载,网络服务提供者是谁写在前面#xff1a;大家好#xff01;我是晴空๓。如果博客中有不足或者的错误的地方欢迎在评论区或者私信我指正#xff0c;感谢大家的不吝赐教。我的唯一博客更新地址是#xff1a;https://ac-fun.blog.csdn.net/。非常感谢大家的支持。一起加油#xff0c;冲鸭#x… 写在前面大家好我是晴空๓。如果博客中有不足或者的错误的地方欢迎在评论区或者私信我指正感谢大家的不吝赐教。我的唯一博客更新地址是https://ac-fun.blog.csdn.net/。非常感谢大家的支持。一起加油冲鸭 用知识改变命运用知识成就未来加油 (ง •̀o•́)ง (ง •̀o•́)ง 文章目录 前言依赖注入方式基于构造法方法的注入基于Setter方法的注入基于字段注入基于方法注入 配置方式示例代码基于XML文件的配置注入pom依赖相关标签bean标签constructor-arg标签property标签 XML实现构造器注入XML实现Setter方法注入 基于注解的配置注入将一个类声明为Bean的注解可注入依赖的注解基于XML和注解混合方式 基于Java类的配置注入ComponentScanBean 前言 Spring 框架对于 Java 服务端开发无疑是一个举足轻重的存在它以简洁、高效、灵活的特性为我们开发提供了强大的支持极大的提高了我们的开发效率和代码质量。Spring 解决了一个非常重要的问题它可以通过 XML 或者 注解 来管理对象之间的依赖关系也就是 Spring 的依赖注入机制。 依赖注入Dependency InjectionDI 作为 Spring 核心理念之一贯穿于整个框架的使用之中。通过依赖注入Spring容器在创建一个对象时会自动将这个对象的依赖注入进去就不需要程序员主动通过 new对象 的方式进行对象创建。Spring 通过依赖注入机制打破了传统编程中对象之间紧密耦合的局面让各个组件能够更加独立、灵活地进行开发、测试和维护为构建复杂而稳定的软件系统奠定了坚实的基础。Spring 框架提供了多种依赖注入方式本文主要介绍一下 Spring 框架中各种依赖注入的方式。
依赖注入方式 Spring 主要有三种常见的注入方式分别是基于构造方法的注入、基于Setter方法的注入、基于字段注入。还有不经常使用的基于方法注入、接口回调注入。
基于构造法方法的注入 所谓基于构造方法注入就是通过构造方法将依赖项传递给对象。在对象实例化时Spring IoC 容器会根据构造方法的参数类型从容器中查找并注入匹配的依赖项。
public class MyService { private final MyDependency myDependency; Autowired public MyService(MyDependency myDependency) { this.myDependency myDependency; }
} 相比于其他注入方式Spring 官方更推荐构造函数注入。官方文档说明如下(https://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-collaborators.html#beans-setter-injection) 官方推荐使用构造器注入的原因主要有以下几点
依赖完整性构造器注入可以确保在对象创建时所有必需的依赖项都已经被注入从而避免空指针异常。实现不可变对象构造器注入可以将对象实现为不可变对象即对象的状态在创建后不能被修改。不可变对象在多线程环境中更安全因为它们的状态不会被改变。初始化保证通过构造器注入的组件总是以完全初始化的状态返回给客户端调用方代码。组件在使用前已完全初始化减少了潜在的错误。避免过多的构造器参数构造器注入鼓励将类的设计保持简洁避免过多的依赖项。如果一个类有过多的构造器参数这通常是一个糟糕的设计表明该类承担了过多的职责应该进行重构。
基于Setter方法的注入 通过类的 Setter 方法来注入依赖项。适用于可选依赖或易于变更的配置属性的场景因为对象可以先创建一个默认状态然后再通过 Setter 方法补充注入依赖。基于 Setter 方法注入的一个好处是Setter 方法使得该类的对象便于以后重新配置或重新注入。
public class MyService { private MyDependency myDependency; Autowired public void setMyDependency(MyDependency myDependency) { this.myDependency myDependency; }
}基于字段注入 基于字段注入直接通过注解Autowired、Resource、Inject将依赖项注入到目标类的字段中。这是最简洁的方式但通常不推荐使用。
public class MyService { Autowired private MyDependency myDependency;
}基于方法注入 通过普通方法非Setter方法注入依赖项。这种方式较为灵活但使用较少。
public class MyService { public void performAction(Autowired MyDependency myDependency) { myDependency.doSomething(); }
}配置方式 以上这些注入方式主要通过三种方式进行配置分别是基于XML文件的配置、基于注解的配置和基于Java类的配置。其中基于XML文件的配置是 Spring 早期的配置方式现在使用的比较少。目前我们常用的配置方式主要是后两种。但是第一种方式也是需要了解的如果看一些老项目的话还是需要掌握一下。
示例代码 为了方便展示写了一个简单的计算器该计算器只实现了加减乘除操作我们需要在计算器的 Controller 类中注入加减乘除服务的实现类 ServiceImpl
// CalculatorApplication类
package com.qingkong.application;import com.qingkong.calculator.CalculatorController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class CalculatorApplication {public static void main(String[] args) {// 加载Spring的配置文件ApplicationContext context new ClassPathXmlApplicationContext(beans.xml);// 获取 CalculatorController BeanCalculatorController calculatorController context.getBean(CalculatorController.class);// 测试计算器的功能System.out.println(calculatorController.add(1, 2));}
}---
// CalculatorService 接口
package com.qingkong.service;public interface CalculatorService {double add(double a, double b);double subtract(double a, double b);double multiply(double a, double b);double divide(double a, double b);
}---
// CalculatorService 接口实现类
package com.qingkong.service.impl;import com.qingkong.service.CalculatorService;public class CalculatorServiceImpl implements CalculatorService {public CalculatorServiceImpl() {System.out.println(CalculatorServiceImpl无参构造方法被调用了);}Overridepublic double add(double a, double b) {return a b;}Overridepublic double subtract(double a, double b) {return a - b;}Overridepublic double multiply(double a, double b) {return a * b;}Overridepublic double divide(double a, double b) {if (b 0) {throw new IllegalArgumentException(不能除以0!);}return a / b;}
}基于XML文件的配置注入
pom依赖 要想实现 Spring 的依赖注入功能需要引入 spring-context 依赖。spring-context 模块是 Spring 框架的核心模块之一它提供了支持 Spring 应用上下文和事件驱动模型的功能。它构建在 spring-core 和 spring-beans 模块之上提供了以下功能
依赖注入DI支持通过 XML 配置、注解或 Java 配置进行依赖注入。应用上下文ApplicationContext提供了更高级的上下文接口如 ClassPathXmlApplicationContext 和 FileSystemXmlApplicationContext用于加载配置文件和管理 Bean。事件支持支持事件发布和监听。 我们只在 pom.xml 中引入 spring-context 依赖Maven 会根据 依赖传递 自动将 spring-core、spring-bean、spring-aop等spring-context依赖的其他 Spring 模块引入。这些模块是 spring 框架的核心模块真实的开发场景下还会引入其他模块。
dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.3.30/version
/dependency相关标签
bean标签 在 XML 中我们可以通过 bean 标签来配置一个bean该标签主要的元素如下所示
属性作用idBean 的唯一标识符用于在 Spring 容器中引用该 BeanclassBean 的全限定类名scope定义 Bean 的作用域如 singleton、prototype 等autowire指定自动装配的方式如 byName、byType 等factory-bean指定一个工厂 Bean用于创建当前 Beanfactory-method指定工厂 Bean 中用于创建当前 Bean 的方法与 factory-bean 配合使用parent指定当前 Bean 的父 Beanlazy-init指定是否延迟初始化该 Beandepends-on指定该 Bean 依赖的其他 Beanprimary标记当前 Bean 为优先选择的 Beaninit-method指定 Bean 初始化时执行的方法destroy-method指定 Bean 销毁时执行的方法
constructor-arg标签 XML 配置文件使用 constructor-arg/ 标签传入构造方法所需要的内容。该标签主要的属性如下
属性作用ref传给构造方法参数的Bean IDvalue传给构造方法参数的值type构造方法参数对应的类型index构造方法参数对应的位置从0开始计算name构造方法参数对应的名称
property标签 使用 property/ 可以为 Bean 的属性赋值或注入其他 Bean。该标签主要的元素如下
属性作用name指定要设置的属性名称value指定要注入的属性值ref引用另一个 Bean 的 Bean ID
XML实现构造器注入 对于 CalculatorController 类先生成该类的构造方法然后将其依赖的 CalculatorService 类作为构造方法的参数注入。完成之后在 XML 文件中进行配置具体实现如下
CalculatorController类
public class CalculatorController {private final CalculatorService calculatorService;// 构造器注入public CalculatorController(CalculatorService calculatorService) {System.out.println(开始进行构造器注入);this.calculatorService calculatorService;}public double add(double a, double b) {return calculatorService.add(a, b);}public double subtract(double a, double b) {return calculatorService.subtract(a, b);}public double multiply(double a, double b) {return calculatorService.multiply(a, b);}public double divide(double a, double b) {return calculatorService.divide(a, b);}
}XML配置文件
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd!-- 定义 CalculatorService 的 Bean --bean idcalculatorService classcom.qingkong.service.impl.CalculatorServiceImpl/!-- 定义 CalculatorController 的 Bean使用构造器注入 --bean idcalculatorController classcom.qingkong.calculator.CalculatorController constructor-arg refcalculatorService//bean/beansXML实现Setter方法注入 首先在 CalculatorController 类中设置 calculatorService 的类型的属性然后生成 Set 方法。完成之后在 XML 文件中进行配置具体实现如下
CalculatorController类
public class CalculatorController {private CalculatorService calculatorService;// Set方法public void setCalculatorService(CalculatorService calculatorService) {System.out.println(开始进行Setter方法注入);this.calculatorService calculatorService;}public double add(double a, double b) {return calculatorService.add(a, b);}public double subtract(double a, double b) {return calculatorService.subtract(a, b);}public double multiply(double a, double b) {return calculatorService.multiply(a, b);}public double divide(double a, double b) {return calculatorService.divide(a, b);}
}XML配置文件
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd!-- 定义 CalculatorService 的 Bean --bean idcalculatorService classcom.qingkong.service.impl.CalculatorServiceImpl/!-- 定义 CalculatorController 的 Bean使用Setter方法注入 --bean idcalculatorController classcom.qingkong.calculator.CalculatorController !-- name属性的值对应 calculatorController 方法中相关属性的名称 --property namecalculatorService refcalculatorService//bean/beans基于注解的配置注入 使用注解注入有两种方式分别是基于XML和注解混合方式 和 纯注解方式。第一种方式需要在 XML 文件中配置 context:component-scan 标签而基于纯注解方式则不需要进行任何 XML 配置只需要在配置类中加入 ComponentScan 注解并执行扫描包路径即可。
将一个类声明为Bean的注解 在 XML配置注入 中我们通过 bean/ 配置一个 Bean而在基于注解的配置时我们只需要在类上面添加如下四个注解中的任意一个都能让 Spring 容器把他们配置为 Bean。
注解说明Component将类标识为普通的BeanService用于标识服务层的类Controller用于标识控制器层Controller的类后来针对REST服务又增加了一个RestController注解Repository用于标识数据访问层的类与数据库进行交互 这四个注解本质上没有区别而且后面三个注解都是 Component 注解的衍生注解之所以这么做主要是为了在分层架构中提供更好的语义化支持和分层的明确性提高代码的可读性和可维护性。
可注入依赖的注解 Spring 内置的 Autowired 以及 JDK 内置的 Resource 和 Inject 都可以用于注入 Bean。这里需要注意的是 Autowired 默认的注入方式为 byType根据类型进行匹配如果一个接口存在多个实现类Spring 会同时找到多个满足条件的选择这种情况下注入方式会变为 byName根据名称进行匹配这个名称通常就是类名首字母小写。 如果一个接口有多个实现类一般建议使用 Autowired 和 Qualifier 注解配合的方式来显式指定名称而不是依赖变量的名称来区分。Qualifier 注解主要用来在依赖注入时消除歧义。当面对一个接口有多个实现类我们可以使用 Qualifier(“类名”) 的方式使 Spring 在依赖注入时准确的找到依赖。 Resource 默认注入方式为 byName。如果无法通过名称匹配到对应的 Bean 时注入方式会变为 byType。 该注解 name 和 type 有两个重要的属性。如果仅指定 name 属性则注入方式为 byName如果仅指定 type属性则注入方式为 byType如果同时指定 name 和 type 属性不建议这么做则注入方式为byType byName。
基于XML和注解混合方式
CalculatorServiceImpl类
Component
public class CalculatorServiceImpl implements CalculatorService {// 省略重复代码……
}CalculatorController类
Component
public class CalculatorController {Autowiredprivate CalculatorService calculatorService;public double add(double a, double b) {return calculatorService.add(a, b);}public double subtract(double a, double b) {return calculatorService.subtract(a, b);}public double multiply(double a, double b) {return calculatorService.multiply(a, b);}public double divide(double a, double b) {return calculatorService.divide(a, b);}
}XML文件
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd!-- 开启注解并扫描指定包中带有注解的类 --context:component-scan base-package com.qingkong//beans基于Java类的配置注入 从 Spring Framework 3.0 开始我们可以使用 Configuration 注解定义配置类可以达到替换 XML 配置文件的效果。使用 Configuration、Bean、ComponentScan 等一系列注解基本可以满足日常开发所需。
我们只需要将原来的 XML 配置文件删除再加上带有 Configuration 注解的配置类即可。
配置类代码
Configuration
ComponentScan(com.qingkong)
public class Config {
}当使用时需要通过 AnnotationConfigApplicationContext 对象来加载我们定义的配置类。
// 加载Spring的配置类
ApplicationContext context new AnnotationConfigApplicationContext(Config.class);
// 获取 CalculatorController Bean
CalculatorController calculatorController context.getBean(CalculatorController.class);ComponentScan ComponentScan 注解指定了类扫描的包名作用与 XML 配置文件中的 context:component-scan/ 类似。如果配置类的 ComponentScan 没有指定扫描的基础包路径或者类那么默认从该配置类的包开始扫描最好还是指定路径防止漏包。该注解的 includeFilters 和 excludeFilters 属性可以用来指定包含和排除组件。官网中也给出了相应的示例
Configuration
ComponentScan(basePackages org.example,includeFilters Filter(type FilterType.REGEX, pattern .*Stub.*Repository),excludeFilters Filter(Repository.class))
public class AppConfig {...
}该配置类与以下 XML配置 等效
beanscontext:component-scan base-packageorg.examplecontext:include-filter typeregexexpression.*Stub.*Repository/context:exclude-filter typeannotationexpressionorg.springframework.stereotype.Repository//context:component-scan
/beansBean 我们也可以在配置类将 Bean 注解放在方法上面这样方法的返回对象就会被当做容器的一个 Bean。默认情况下Bean 名称与方法名称相同。官网给出了使用例子
Configuration
public class AppConfig {Beanpublic TransferService transferService() {return new TransferServiceImpl();}
}该配置与以下 XML 中的配置是等价的
beansbean idtransferService classcom.acme.TransferServiceImpl/
/beans既然有了 Component 等注解为什么还要用 Bean 注解呢Component 注解作用于类而 Bean 注解作用于方法。当我们引用第三方库中的类需要装配到 Spring 容器时只能用 Bean 注解来实现因为通常情况下我们是无法修改第三方类库的代码的。 https://docs.spring.io/spring-framework/docs/5.2.x/spring-framework-reference/core.html#spring-core《学透Spring 从入门到项目实战》JavaGuide