Spring IoC&DI(2)

这篇具有很好参考价值的文章主要介绍了Spring IoC&DI(2)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

IoC详解

通过上面的案例, 我们已经知道了IoC和DI的基本操作, 接下来我们来系统地学习Spring IoC和DI的操作.

前面我们提到的IoC控制反转, 就是将对象的控制权交给Spring的IoC容器, 由IoC容器创建及管理对象.  (也就是Bean的存储).

Bean的存储

我们之前只讲到了@Component注解来使得对象交给IoC容器管理. 而Spring为了更好地管理Web应用程序, 提供了更丰富的注解.

当前有两类注解:

1.类注解@Controller(控制器存储), @Service(服务存储), @Reposity(仓库), @Component(组件), @Configuration(配置)

2.方法注解: @Bean

 类注解的使用

由于这里五个类注解在功能上基本是一致的, 所以这里用@Controller进行介绍.

使用@Controller存储bean的代码如下所示:

@Controller //将对象存储到Spring中
public class MyController {
    public void sayHi() {
        System.out.println("Hi, UserController...");
    }
}

如何观察这个对象已经存在Spring容器当中了呢?

接下来我们学习如何从Spring容器中获取对象.

@SpringBootApplication
public class SpringbootDemoApplication {
	public static void main(String[] args) {
		//获取Spring上下文对象
		ApplicationContext context = SpringApplication.run(SpringbootDemoApplication.class);
		//从Spring上下文中获取对象
		MyController myController = context.getBean(MyController.class);
		//获取对象
		myController.sayHi();
	}
}

ApplicationContext 翻译过来就是: Spring上下文.

因为对象交给Spring管理, 所以获取对象要从Spring中获取, 那么就得先得到Spring的上下文.

关于上下文的概念

在计算机领域, 上下文这个概念, 我们之前在在进程PCB核心属性讲过, 它是指支持进程调度的重要属性. 等下次调度回CPU时,会把寄存器上的回复回来.

这里的上下文, 就是指当前的运行环境, 也可以看作是一个容器, 容器里存很多内容, 这些内容是当前运行的环境. 

观察运行结果, 发现成功从Spring中获取到Controller对象, 并执行Controller的SayHi方法.

Spring IoC&DI(2),JavaEE进阶,spring,java,数据库

 获取bean对象的其他方式

上述代码是根据类型来查找对象, 如果Spring容器中, 同一个类型存在多个bean的话, 怎么获取呢?

ApplicationContext也提供了其它获取bean的方式, ApplicationContext获取bean对象的功能, 是父类BeanFactory提供的功能.

Spring IoC&DI(2),JavaEE进阶,spring,java,数据库

可以发现, 我们获取bean共有五种方法, 而常用的是第1, 2, 4三种. 第一种是根据名称获取bean对象, 第二种是通过名称, 类型获取bean对象. 第三种是通过类型获取对象.

其中1,2种都涉及根据名称来获取对象, bean的名称是什么呢?

Spring bean是Spring框架在运行时管理的对象, Spring会给管理的对象起一个名字.

比如学校管理学生, 会给每个学生分配一个学号, 根据学号, 可以找到对应学生.

Spring也是如此, 给每个对象起一个名字, 根据Bean名称(BeanId)就可以获取到对应对象. 

Bean命名约定

程序开发人员不需要为bean指定名称(BeanId), 如果没有显式提供名称(BeanId), Spring容器将为该bean生成唯一的名称.

命名约定使用Java标准约定作为实例字段名, 也就是说bean名称以小写字母开头, 然后使用驼峰时大小写.

eg. MyController -> myController

也有一些特殊情况, 当有多个字符且第一个和第二个字符都大写时, 将保留原始的大小写. 

eg. UController -> UController

根据这个规则, 我们来获取Bean.

@SpringBootApplication
public class SpringbootDemoApplication {
	public static void main(String[] args) {
		//获取Spring上下文对象
		ApplicationContext context = SpringApplication.run(SpringbootDemoApplication.class);
		//根据bean类型, 从Spring上下文中获取对象.
		MyController myController1 = context.getBean(MyController.class);
		//根据bean名称, 从Spring上下文中获取对象
		MyController myController2 = (MyController) context.getBean("myController");
		//根据bean名称+对象, 从Spring上下文中获取对象
		MyController myController3 = context.getBean("myController", MyController.class);
		//使用对象
		System.out.println(myController1);
		System.out.println(myController2);
		System.out.println(myController3);
	}
}

运行结果:

Spring IoC&DI(2),JavaEE进阶,spring,java,数据库

地址一样, 说明对象是一个.

获取bean对象, 是父类BeanFactory提供的功能.

ApplicationContext VS BeanFactory (面试题)

继承关系和功能来说: Spring有两个顶级的接口: ApplicationContext 和BeanFactory. 其中

BeanFactory提供了基础的访问容器的能力, 而Application属于BeanFactory的子类. 它除了继承BeanFactory的所有功能之外, 还有独特的特性: 对国际化的支持, 资源访问支持, 以及事件传播方面的支持. 

从性能来说: ApplicationContext是一次性加载并初始化的所有Bean对象(可类似于饿汉模式),BeanFactory是需要哪个再去加载哪个, 因此更加轻量.(空间换时间) (一般建议用ApplicationContext, 因为现在机器的性能更高了). 

为什么要这么多类注解?

这个也是和前面讲的应用分层相呼应. 让程序员看到注解之后, 就能知道这个类的用途.

@Controller: 控制层, 接收请求, 对请求进行处理, 并进行响应.

@Service: 业务逻辑层,处理具体的逻辑.

@Respository: 数据访问层, 也称为持久层. 负责数据的访问操作.

@Configuration: 配置层. 处理项目中的一些配置信息. 

这个就类似于车牌号的功能, 一看开头, 不管后面的字符串是什么, 就能知道这个车是哪里的. 

程序的应用分层, 调用逻辑如下:

Spring IoC&DI(2),JavaEE进阶,spring,java,数据库

类注解之间的关系

查看@Controller, @Configuration, @Repository, @Service的源码发现:

这些注解中其实都有一个元注解: @Component, 说明它们本身就属于@Component的"子类", 说明它们本身就是属于@Component的"子类". @Component是一个元注解, 也就是说可以注解其它类注解, 如@Controller, @Service, @Repository, 这些注解都可以说是@Component的衍生注解.

方法注解@Bean

类注解是添加到某个类上的, 但是存在两个问题:

1.使用外部包里的类, 没办法添加类注解

2.一个类, 需要多个对象, 比如多个数据源.

 这种场景, 我们就需要注解@Bean

方法注解需要配合类注解使用

在Spring框架的设计中, 方法注解@Bean要配合类注解才能将对象正常地存储到Spring容器中.

举个栗子:

@Component
public class BeanConfig {

    @Bean
    public User user() {
        User user = new User();
        user.setName("lisi");
        user.setAge(20);
        return user;
    }
}

 运行下述代码:

@SpringBootApplication
public class SpringbootDemoApplication {
	public static void main(String[] args) {
		//获取Spring上下文对象
		ApplicationContext context = SpringApplication.run(SpringbootDemoApplication.class);
		User user = context.getBean(User.class);
		System.out.println(user);
	}
}

得到运行结果:

Spring IoC&DI(2),JavaEE进阶,spring,java,数据库

定义多个对象

对于同一个类, 如何定义多个对象呢?

比如多数据源的场景, 类是同一个, 但是配置不同, 指向不同的数据源. 

我们看下@Bean的使用

@Component
public class BeanConfig {

    @Bean
    public User user1() {
        User user = new User();
        user.setName("lisi");
        user.setAge(20);
        return user;
    }

    @Bean
    public User user2() {
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
}

当定义到多个对象时, 我们继续使用上面的代码, 能获取到什么对象? 我们来运行一下:

Spring IoC&DI(2),JavaEE进阶,spring,java,数据库

报错信息显示:期望只有一个匹配, 结果却发现了两个: user1, user2.

从报错信息中, 可以看出来, @Bean注解的bean, bean名称就是它的方法名.

接下来以正确的方式来获取Bean对象.

@SpringBootApplication
public class SpringbootDemoApplication {
	public static void main(String[] args) {
		//获取Spring上下文对象
		ApplicationContext context = SpringApplication.run(SpringbootDemoApplication.class);
		User user1 = (User) context.getBean("user1");
		User user2 = (User) context.getBean("user2");
		System.out.println(user1);
		System.out.println(user2);
	}
}

运行结果: 

Spring IoC&DI(2),JavaEE进阶,spring,java,数据库

可以看到, @Bean针对同一个类, 定义多个对象.

重命名Bean

@Bean(name = {"u1", "user1"}) 

添加类似的注解仍可以运行成功, 这是将user1重命名为u1的一种方式. 类似地, 还有如下方式:

@Bean({"u1", "user1"})

//只有一个名称时, 其它的内容可以省略.

@Bean("u1")

扫描路径

使用前面注解声明的bean, 一定会生效吗?

不一定(原因: bean想要生效, 还需要被Spring扫描).

当在同一个包内, 可以直接被Spring扫描到, 如果不在同一个包, 就可以通过@ComponentScan来配置扫描路径.

@ComponentScan({"com.example.demo"})
@SpringBootApplication
public class SpringIocDemoApplication {
    public static void main(String[] args) {
        //获取Spring上下⽂对象
        ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class);
        //从Spring上下⽂中获取对象
        User u1 = (User) context.getBean("u1");
        //使⽤对象
        System.out.println(u1);
    }
}

{}里可以配置多个包路径.

这种做法仅作了解, 不做推荐使用. 文章来源地址https://www.toymoban.com/news/detail-846515.html

到了这里,关于Spring IoC&DI(2)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【学习】Spring IoC&DI

    🎥 个人主页:Dikz12 📕格言:吾愚多不敏,而愿加学 欢迎大家👍点赞✍评论⭐收藏 目录 Spring 是什么? 什么是 IoC容器? 传统开发模式  loC开发模式 IoC的优势  IoC 的使用 Bean的存储   方法注解  DI  属性注入  构造⽅法注⼊  Setter 注⼊ @Autowired存在的问题  解决方案:

    2024年04月15日
    浏览(33)
  • Spring IoC&DI(2)

    通过上面的案例, 我们已经知道了IoC和DI的基本操作, 接下来我们来系统地学习Spring IoC和DI的操作. 前面我们提到的IoC控制反转, 就是将对象的控制权交给Spring的IoC容器, 由IoC容器创建及管理对象.  ( 也就是Bean的存储 ). 我们之前只讲到了@Component注解来使得对象交给IoC容器管理

    2024年04月10日
    浏览(36)
  • Spring IOC DI - 整合MyBatis

    Spring 框架的优势(对比以前项目的缺点) (1)单纯使用Mybatis框架,业务层代码复杂,需要用大量的代码自行解析mybatis.xml配置文件,压力都给到了业务层代码,如下代码: 学习了spring以后,mybaits的使用会更加简单,会简化业务层处理的代码。 (2)层与层之间的耦合性太高了

    2024年02月04日
    浏览(33)
  • 【Spring篇】IOC/DI注解开发

    🍓系列专栏:Spring系列专栏 🍉个人主页:个人主页 目录 一、IOC/DI注解开发 1.注解开发定义bean  2.纯注解开发模式 1.思路分析 2.实现步骤 3.注解开发bean作用范围与生命周期管理 1.环境准备 2.Bean的作用范围 3.Bean的生命周期 4.注解开发依赖注入 1.环境准备 2.注解实现按照类型注入

    2024年02月03日
    浏览(64)
  • 什么是IoC?什么是Spring IoC?什么是DI?

    首先说明 IoC 是一种思想,IoC的全称是Inversion of Control,翻译成中文叫做 “控制反转” 用人话来说,IoC的思想就是将一个对象对另一个对象的控制权交出去(不必关心交给谁),从而让对象之间的依赖关系降低,降低代码之间耦合程度。 我们可以写一个简单的代码来举个例子

    2024年02月14日
    浏览(40)
  • Spring框架中IOC和DI详解

    来源黑马Spring课程,觉得挺好的 1、为什么要学习spring? 如果让本人用一句话去回答这个问题,那么我只能说:在J2EE的学习之路上,spring给我带来了开发的春天,让我们从JSP、sevlet的高耦合的开发中彻底的解救出来。 spring是目前最主流的框架 spring是学习后面课程(比如:

    2023年04月15日
    浏览(44)
  • 一文吃透 Spring 中的IOC和DI

    ✅作者简介:2022年 博客新星 第八 。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏:SSM 框架从入门到精通 ✨特色专栏:国学周更-心性养成之路 🥭本文内容:一文吃透 Spring 中

    2024年01月25日
    浏览(44)
  • spring--Ioc控制反转/DI依赖注入

    1.概念:在使用对象的时候,由主动的new转换为外部提供对象,将对象创建的控制权交给外部,即控制反转 2.spring提供了一个容器,称为IOC容器,用来从当ioc中的外部 3.被管理或者被创建的对象在ioc中被叫做bean 使用步骤 1.导入依赖 spring-context 依赖,用到xml文件就需导入 2.创建

    2024年02月12日
    浏览(33)
  • Spring 是什么?IoC 和 DI的区别

    我们通常讲的Spring指的是Spring Framework(Spring框架),它是一个开源的框架,有着活跃而庞大的社区,这也是它之所谓经久不衰的原因。官方的解读是:Spring官网 翻译过来就是:Spring使Java编程对每个人来说更快、更容易、更安全。Spring对速度、简单性和生产力的关注使它成为全球最受欢

    2024年02月08日
    浏览(32)
  • Spring框架IOC容器和DI依赖注入

    IOC(Invertion Of Control):控制反转,使用对象时,由使用new创建对象转变为由外部提供对象,此过程中对象的创建控制权由程序转移到外部的思想称之为控制反转. DI(Dependency Injection):依赖注入,在容器中建立bean与bean之间的关系的过程,称之为依赖注入 pom.xml依赖引入 BookDao BookDaoImpl Book

    2023年04月09日
    浏览(74)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包