伙计,是时候拉近你和【Spring】之间的距离了!

简介: 本文主要介绍 Spring 中的核心之一 IOC

什么是Spring:


  • Spring 是一个开源框架


  • Spring 为简化企业级应用开发而生. 使用 Spring 可以使简单的 JavaBean 实现以前只有 EJB 才能实现的功能


  • Spring 是一个 IOC(DI) 和 AOP 容器框架.


具体描述:


  • 轻量级:Spring 是非侵入性的 - 基于 Spring 开发的应用中的对象可以不依赖于 Spring 的 API


  • 依赖注入(DI --- dependency injection、IOC)


  • 面向切面编程(AOP --- aspect oriented programming)


  • 容器: Spring 是一个容器, 因为它包含并且管理应用对象的生命周期


  • 框架: Spring 实现了使用简单的组件配置组合成一个复杂的应用. 在 Spring 中可以使用 XML 和 Java 注解组合这些对象


  • 一站式:在 IOC 和 AOP 的基础上可以整合各种企业应用的开源框架和优秀的第三方类库 (实际上 Spring 自身也提供了展现层的 SpringMVC 和 持久层的 Spring JDBC)


Spring 核心模块:



IOC 和 DI


  • IOC(Inversion of Control):其思想是反转资源获取的方向. 传统的资源查找方式要求组件向容器发起请求查找资源. 作为回应, 容器适时的返回资源. 而应用了 IOC 之后, 则是容器主动地将资源推送给它所管理的组件, 组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式。


  • DI(Dependency Injection) — IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如: setter 方法)接受来自如容器的资源注入. 相对于 IOC 而言,这种表述更直接。


搭建 Spring 开发环境:


1)所需Jar包



2)Spring配置文件


一个典型的 Spring 项目需要创建一个或多个 Bean 配置文件, 这些配置文件用于在 Spring IOC 容器里配置 Bean. Bean 的配置文件可以放在 classpath 下, 也可以放在其它目录下.



3)例子


  • 创建一个类:


public class Person {
 private String name;
 public Person() {
  System.out.println("Person's constructor...");
 }
 public Person(String name) {
  this.name = name;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
}


  • 传统方式获取这个类:


Person person = new Person();
person.setName("Cbuc");
person.hello();


  • Spring 管理:


  • 在beans.xml中注入bean:


/** 
* class: 通过全类名的方式配置Bean
*    id:Bean的名称; 
*    - 在 IOC 容器中必须是惟一的;
*    - 若 id 没有指定,Spring 自动将权限定性类名作为 Bean 的名字
*    - id 可以指定多个名字,名字之间可用逗号、分号、或空格分隔 
*/
/**
* 依赖注入的方式
*   1)属性注入
*   2)构造器注入
*   3)工厂方法注入(很少使用,不推荐)
*/
<!-- 通过 setter 方法注入属性值 -->
<bean id="person1" class="cbuc.life.test_01.Person">
 <!-- 为属性赋值 -->
 <!-- 通过属性注入: 通过 setter 方法注入属性值 -->
 <property name="name" value="Cbuc"></property>
</bean>
<!-- 通过构造器注入属性值 -->
<bean id="person2" class="cbuc.life.test_01.Person">
 <!-- 要求: 在 Bean 中必须有对应的构造器.  -->
 <constructor-arg value="Cbuc"></constructor-arg>
</bean>


  • 注入完成,获取Bean:


/**
* 在 Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC 容器里获取 Bean 实例并使用.
* Spring 提供了两种类型的 IOC 容器实现. 
*   1)BeanFactory: IOC 容器的基本实现.
*   2)ApplicationContext: 提供了更多的高级特性. 是 BeanFactory 的子接口.
* BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory
*/
//1.  Spring 装配 IOC
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
//2. 通过 IOC 获取 bean "person1"  通过指定ID的方式
Person person = (Person) ctx.getBean("Person2");
//通过指定类型的方式,弊端:如果IOC中配置了多个Person类,那么将会不知道为你注入那个Bean
//Person perosn1 = ctx.getBean(Person.class);


小菜与你小结


构造方法注入引入的问题


场景1: 当一个类中有两个构造方法


new Person("Cbuc",22,"男"):我想使用的是第二个构造方法给age赋值,但是却进入到了第一个构造方法中,为salary赋值.



解决: 按类型匹配入参



成功为age赋值:



场景2: 当一个类中有个构造方法


bean注入属性的时候没有按照构造方法的顺序注入



那么获得Bean的时候成功报错



解决: 按索引匹配入参



字面值


  • 可用字符串表示的值,可以通过 元素标签或 value 属性进行注入。


  • 基本数据类型及其封装类、String 等类型都可以采取字面值注入的方式


  • 若字面值中包含特殊字符,可以使用 把字面值包裹起来。


<bean id="person4" class="cbuc.life.test_01.Person">
 <property name="name">
  <!-- 若字面值中包含特殊字符, 则可以使用 DCDATA 来进行赋值 -->
  <value><![CDATA[<Cbuc>]]></value>
 </property>
 <property name="age" value="22"></property>
 <property name="gender" value="1"></property>
</bean>



引用其它 Bean


场景: Person 中需要一个 Car 类



解决:


首先在IOC中注入Car:


<bean id="Mycar" class="cbuc.life.test_01.Car">
 <property name="maxSpeed" value="220"></property>
 <property name="price" value="200000"></property>
 <property name="brand" value="WEY"></property>
</bean>


方法一: 通过 ref 在person中引用:



方法二: 内部Bean(注意内部Bean只能当前Bean使用,外部不能引用!)



设置级联属性



设置集合属性


  • List



  • Map


  • Set与List用法一致


  • 属性集合



  • 数组



p 命名空间的使用



自动装配


  • byType(根据类型自动装配):


若 IOC 容器中有多个与目标 Bean 类型一致的 Bean. 在这种情况下, Spring 将无法判定哪个 Bean 最合适该属性, 所以不能执行自动装配.


  • byName(根据名称自动装配):


必须将目标 Bean 的名称和属性名设置的完全相同.


  • Constructor(通过构造器自动装配) : 不推荐使用


Bean中的继承(parent)


  • 子 Bean 从父 Bean 中继承配置, 包括 Bean 的属性配置



  • 子 Bean 也可以覆盖从父 Bean 继承过来的配置



  • 父 Bean 可以作为配置模板, 也可以作为 Bean 实例. 若只想把父 Bean 作为模板, 可以设置 的abstract 属性为 true, 这样 Spring 将不会实例化这个 Bean



  • 并不是  元素里的所有属性都会被继承. 比如: autowire,abstract 等.


  • 可以忽略父 Bean 的 class 属性, 让子 Bean 指定自己的类, 而共享相同的属性配置. 但此时 abstract 必须设为 true


依赖 Bean 配置


  • Spring 允许用户通过 depends-on 属性设定 Bean 前置依赖的Bean,前置依赖的 Bean 会在本 Bean 实例化之前创建好



  • 如果前置依赖于多个 Bean,则可以通过逗号,空格或的方式配置 Bean 的名称


使用外部属性文件


  • Spring 提供了一个 PropertyPlaceholderConfigurerBeanFactory 后置处理器, 这个处理器允许用户将 Bean 配置的部分内容外移到属性文件中. 可以在 Bean 配置文件里使用形式为 ${var} 的变量, PropertyPlaceholderConfigurer 从属性文件里加载属性, 并使用这些属性来替换变量.



Spring表达式语言(SpEL)


  • Spring 表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言。


  • 语法类似于 EL:SpEL 使用 #{…} 作为定界符,所有在大框号中的字符都将被认为是 SpEL


  • SpEL 为 bean 的属性进行动态赋值提供了便利


通过 SpEL 可以实现:


  • 通过 bean 的 id 对 bean 进行引用


  • 调用方法以及引用对象中的属性


  • 计算表达式的值


  • 正则表达式的匹配



  • 字面量的表示:


  • 整数:
  • 小数:
  • 科学计数法:
  • String可以使用单引号或者双引号作为字符串的定界符号:
  • Boolean:


Bean 的生命周期


  1. 在Person类中自定义 Init 和 destroy 方法



  1. 在注入Bean的时候声明两个方法



在 classpath 中扫描组件


  • 组件扫描(component scanning):  Spring 能够从 classpath 下自动扫描, 侦测和实例化具有特定注解的组件.


  • 特定组件包括:


  • @Component: 基本注解, 标识了一个受 Spring 管理的组件
  • @Respository: 标识持久层组件
  • @Service: 标识服务层(业务层)组件
  • @Controller: 标识表现层组件


  • 对于扫描到的组件, Spring 有默认的命名策略:


  • 使用非限定类名, 第一个字母小写.
  • 在注解中通过 value 属性值标识组件的名称


  • 当在组件类上使用了特定的注解之后, 还需要在 Spring 的配置文件中声明


  • base-package 属性指定一个需要扫描的基类包,Spring 容器将会扫描这个基类包里及其子包中的所有类.
  • 当需要扫描多个包时, 可以使用逗号分隔.
  • 如果仅希望扫描特定的类而非基包下的所有类,可使用 resource-pattern 属性过滤特定的类,示例:



目录
相关文章
|
5月前
|
机器学习/深度学习 人工智能 自然语言处理
人工智能应用领域有哪些
本文全面探讨了人工智能(AI)的应用领域和技术核心,涵盖医疗、交通、金融、教育、制造、零售等多个行业,并分析了AI技术的局限性及规避策略。同时,介绍了生成式人工智能认证项目的意义与展望。尽管AI发展面临数据依赖和算法可解释性等问题,但通过优化策略和经验验证,可推动其健康发展。未来,AI将在更多领域发挥重要作用,助力社会进步。
|
10月前
|
并行计算 算法 安全
未来科技:量子计算的崛起与挑战
【10月更文挑战第21天】 本文深入探讨了量子计算这一前沿科技领域的最新进展、核心原理以及面临的主要挑战。通过对比经典计算与量子计算的差异,揭示了量子计算在处理复杂问题时的独特优势。同时,文章还展望了量子计算在未来可能带来的颠覆性变革,并对其发展过程中需要克服的技术难题进行了分析。
302 13
|
7月前
|
传感器 存储 人工智能
一文彻底搞清楚数字电路
数字电路是处理离散二进制信号(0和1)的电子电路,由逻辑门(如与门、或门等)组成,实现各种逻辑运算。它在计算机、通信、自动控制和数字信号处理等领域广泛应用。例如,CPU通过数字电路执行算术和逻辑运算,PLC用于工业自动化控制,数字滤波器则用于信号处理。数字电路以高电平(如5V)表示1,低电平(如0V)表示0,简化了信号处理并提高了系统的可靠性和抗干扰能力。
658 0
一文彻底搞清楚数字电路
|
8月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
173 12
|
9月前
|
人工智能 自然语言处理 算法
魔搭社区每周速递(11.24-11.30)
魔搭ModelScope本期社区进展:1361个模型,29个数据集,44个创新应用,5 篇内容
魔搭社区每周速递(11.24-11.30)
|
Kubernetes Cloud Native Devops
【阿里云云原生专栏】DevOps与云原生的融合:阿里云CI/CD流水线最佳实践
【5月更文挑战第23天】阿里云融合DevOps与云原生技术,提供高效CI/CD解决方案,助力企业提升研发效能。通过云效平台,集成代码管理、构建服务、容器服务、持续部署及监控日志组件,实现自动化研发流程。案例中,应用从GitHub构建到Kubernetes部署,全程无缝衔接。借助阿里云,企业能快速构建适应云原生的DevOps体系,以应对复杂需求和提升市场竞争力。
371 1
|
存储 JSON 前端开发
需要token的原因----
需要token的原因----
403 0
|
存储 关系型数据库 分布式数据库
【PolarDB 开源】PolarDB 数据备份与恢复策略:确保数据安全的最后一道防线
【5月更文挑战第28天】PolarDB 开源数据安全的关键:备份与恢复策略。定期备份(全量+增量)降低数据丢失风险,制定策略考虑多种因素。确保备份存储安全,测试恢复流程有效性,结合监控系统及时处理问题。保留多版本备份,应对灾难情况有预案。培训人员,提高数据安全意识,打造稳固防线。
361 0
|
JSON JavaScript 前端开发
vue的 blob文件下载文件时,后端自定义异常,并返回json错误提示信息,前端捕获信息并展示给用户
vue的 blob文件下载文件时,后端自定义异常,并返回json错误提示信息,前端捕获信息并展示给用户
|
11月前
|
移动开发 前端开发 Android开发
开发指南059-App实现微信扫描登录
App是用uniapp开发的,打包为apk,上传到安卓平板中使用

热门文章

最新文章