当前位置: 首页 > news >正文

[Spring]-组件注入

注入组件

注入组件的各种方式

实验1

理解自动装配

package com.guigu.spring.ioc;/*** 主入口文件*/
@SpringBootApplication
public class Spring01IocApplication {/*** 组件注入**/public static void main(String[] args) {ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);System.out.println("===ioc容器创建完成===");UserService UserController = ioc.getBean(UserService.class);System.out.println("UserController=" + UserController);}}
package com.guigu.spring.ioc.controller;@Controller
public class UserController {/*** 自动装配, 原理: Spring调用容器的getBean方法* 自动装配流程: 先按照类型查找, 再按照名称查找* 1. 先按照类型查找组件*    --> 有且只有一个, 直接注入*    --> 如果找到多个, 再按照名称查询, 变量名就是名称* 2. 按照名称查询*    --> 如果找到, 直接注入*    --> 如果找不到, 报错*/@Autowired // UserService这个类型的组件只有一个, Spring直接按注入按类型注入, 名字无所谓UserService abc;@Autowired // Person这个类型的组件有多个, bill就要是组件的名字, 否则就无法匹配了, 会报错Person bill;@Autowired // 把Person类型的组件都拿到list集合中List<Person> personList;@Autowired // 把Person类型的组件都拿到map集合中, 组件的名字是key, 组件就是keyMap<String, Person> personMap;@Autowired // 拿到整个容器ApplicationContext applicationContext;}
package com.guigu.spring.ioc.service;@Service
public class UserService {
}
package com.guigu.spring.ioc.config;@Configuration // 告诉spring容器, 这是一个配置类
public class PersonConfig {@Bean("joseph")public Person joseph() {return new Person("乔布斯", 18, "男");}@Bean("bill")public Person bill() {return new Person("比尔盖茨", 18, "男");}}

实验2

如果容器中同一类型的bean存在多个, 如果注入失败, 可以使用以下注解解决

最佳实践: 强烈建议组件注册的名字 和 组件注入的名字符合规范, 这样可以避免不必要的麻烦

使用@Primary注解 指定默认组件

package com.guigu.spring.ioc.config;@Configuration // 告诉spring容器, 这是一个配置类
public class PersonConfig {@Primary // 主组件(默认组件)@Bean("joseph")public Person joseph() {return new Person("乔布斯", 18, "男");}@Bean("bill")public Person bill() {return new Person("比尔盖茨", 18, "男");}
}
package com.guigu.spring.ioc.controller;@Controller
public class UserController {@Autowired // Person这个类型的组件有多个, Spring无法按类型匹配唯一组件, 但是设置了默认组件, 可以正确匹配Person abcd;}
package com.guigu.spring.ioc;/*** 主入口文件*/
@SpringBootApplication
public class Spring01IocApplication {/*** 组件注入**/public static void main(String[] args) {ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);System.out.println("===ioc容器创建完成===");UserService UserController = ioc.getBean(UserService.class);System.out.println("UserController=" + UserController);}}

使用@QualiFier注解, 具名注入组件

package com.guigu.spring.ioc.config;@Configuration // 告诉spring容器, 这是一个配置类
public class PersonConfig {@Bean("joseph")public Person joseph() {return new Person("乔布斯", 18, "男");}@Bean("bill")public Person bill() {return new Person("比尔盖茨", 18, "男");}
}
package com.guigu.spring.ioc.controller;@Controller
public class UserController {@Qualifier("bill") // 精确指定组件的名字, 可以解决组件类型不唯一的问题, 如果设置了默认组件, 该注解还可以用于切换默认组件@Autowired // Person这个类型的组件有多个, Spring无法按类型匹配唯一组件Person abcde;}
package com.guigu.spring.ioc;/*** 主入口文件*/
@SpringBootApplication
public class Spring01IocApplication {/*** 组件注入**/public static void main(String[] args) {ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);System.out.println("===ioc容器创建完成===");UserService UserController = ioc.getBean(UserService.class);System.out.println("UserController=" + UserController);}}

实验3

了解 @Resource注解

package com.guigu.spring.ioc.controller;@Controller
public class UserController {/*** 面试题: @Resource 和 @Autowired 区别?* 1. @Resource 和 @Autowired 都是自动装配的注解* 2. @Resource是javax提供的注解,所有的容器框架都支持该注解 ,具有更强的通用性* 3. @Autowired 是Spring提供的注解, 现在spring框架一家独大, 所以一般都用这个注解* 4. @Autowired 默认按照类型装配, 默认情况下依赖对象必须存在, 否则报错, 可以设置required属性为false, 对象不存在时设置为null* 5. @Resource 注解不提供组件可选属性*/@Resource // Person这个类型的组件有多个, Spring无法按类型匹配唯一组件Person abcdef;}

实验4

通过构造器注入bean

  1. 让容器中有dog这个组件
package com.guigu.spring.ioc.bean;public class Dog {}
package com.guigu.spring.ioc.config;@Configuration
public class DogConfig {@Beanpublic Dog dog() {return new Dog();}
}
  1. 利用构造器注入组件
package com.guigu.spring.ioc.dao;@Repository
public class UserMapper {Dog dog;/*** 使用构造器注入组件(官方推荐)*  前提: 1组件中不要声明无参构造器,声明有参构造器*        2组件要交给容器管理*  原理:  Spring 自动去容器中找到构造器需要的对象, 并且注入到构造器中*/public UserMapper(Dog dog) {System.out.println("UserMapper的构造器," + dog);this.dog = dog;}
}
  1. 检查一下: Dog组件有了, 并且在UserMapper创建时, 也被注入了
package com.guigu.spring.ioc;/*** 主入口文件*/
@SpringBootApplication
public class Spring01IocApplication {/*** 组件注入**/public static void main(String[] args) {ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);System.out.println("===ioc容器创建完成===");Dog bean = ioc.getBean(Dog.class);System.out.println("bean=" + bean);}}

实验5

通过setter方法注入组件

  1. 让容器中有dog这个组件
package com.guigu.spring.ioc.bean;public class Dog {}
package com.guigu.spring.ioc.config;@Configuration
public class DogConfig {@Beanpublic Dog dog() {return new Dog();}
}
  1. 利用setter方法注入组件
package com.guigu.spring.ioc.dao;@Repository
public class UserMapper {Dog dog;/*** 通过setter方法注入组件*/@Autowiredpublic void stetDog(Dog dog) {System.out.println("UserMapper的setter方法," + dog);this.dog = dog;}
}
  1. 检查一下: Dog组件有了, 并且在UserMapper创建时, 也被注入了
package com.guigu.spring.ioc;/*** 主入口文件*/
@SpringBootApplication
public class Spring01IocApplication {/*** 组件注入**/public static void main(String[] args) {ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);System.out.println("===ioc容器创建完成===");Dog bean = ioc.getBean(Dog.class);System.out.println("bean=" + bean);}}

实验6

理解感知接口:

  1. Aware是Spring定义的一个接口, 官方为Aware接口定义了很多实现类

  1. ctrl + h 查看接口的所有实现, 这些实现都是感知接口, 想用啥实现啥就行, 下面有例子

  1. 如果组件中需要环境变量, 就直接实现EnvironmentAware, 重写setEnvironment()方法, 就可以拿到环境信息
package com.guigu.spring.ioc.service;@Service
public class TestService implements EnvironmentAware, BeanNameAware {// 保存系统环境变量private Environment environment;// 保存组件名称private String myName;@Overridepublic void setEnvironment(Environment environment) {this.environment = environment;}public String getOsType() {return environment.getProperty("OS");}@Overridepublic void setBeanName(String name) {this.myName = name;}public String getMyName() {return myName;}
}
  1. 运行结果
package com.guigu.spring.ioc;/*** 主入口文件*/
@SpringBootApplication
public class Spring01IocApplication {/*** 组件注入*/public static void main(String[] args) {ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);System.out.println("===ioc容器创建完成===");TestService testService = ioc.getBean(TestService.class);System.out.println("testService=" + testService);String osType = testService.getOsType();System.out.println("osType=" + osType);String myName = testService.getMyName();System.out.println("myName=" + myName);}
}

实验7

使用@Value注解获取配置文件的数据

package com.guigu.spring.ioc.bean;@Data
@Component
public class Dog {/*** 1.@Value("字面量"): 直接赋值* 2.@Value("#{}): 从配置文件中读取数据* 3.@Value("#{SpEL}"): 写Spring表达式语言*/@Value("旺财")private String name;//private String name = "旺财";@Value("${dog.age}")private Integer age;@Value("#{10*20}")private String color;@Value("#{T(java.util.UUID).randomUUID().toString()}")private String id;@Value("#{'Hello World!'.substring(0,5)}")private String msg;@Value("#{1>2? 'heihei' : 'haha'}")private String flg;public Dog() {System.out.println("Dog的构造器...");}public Dog(String name, Integer age, String color) {this.name = name;this.age = age;this.color = color;}
}
package com.guigu.spring.ioc;/*** 主入口文件*/
@SpringBootApplication
public class Spring01IocApplication {/*** 组件注入*/public static void main(String[] args) {ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);System.out.println("===ioc容器创建完成===");Dog bean = ioc.getBean(Dog.class);System.out.println("bean=" + bean);}
}

实验8

指定属性注入的数据源

cat.name="Tom"
cat.age=12
package com.guigu.spring.ioc.bean;/*** @PropertySource指定数据来源: 把指定的文件导入容器中, 供我们使用* 1.classpath:cat.properties: 从自己的项目类路径下找* 2.classpath*:Log4j-charsets.properties: 从所有包的类路径下找*/
@PropertySource("classpath:cat.properties")
@Data
@Component
public class Cat {@Value("${cat.name:Tom}") //:后面的值是取值失败时的默认值private String name;@Value("${cat.age:20}")private String age;
}
package com.guigu.spring.ioc;/*** 主入口文件*/
@SpringBootApplication
public class Spring01IocApplication {/*** 组件注入*/public static void main(String[] args) {ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);System.out.println("===ioc容器创建完成===");Cat bean = ioc.getBean(Cat.class);System.out.println("bean=" + bean);}}

实验9

获取资源

package com.guigu.spring.ioc;/*** 主入口文件*/
@SpringBootApplication
public class Spring01IocApplication {/*** 组件注入*/public static void main(String[] args) throws IOException {ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);System.out.println("===ioc容器创建完成===");File file = ResourceUtils.getFile("classpath:DE.jpg");System.out.println("file=" + file);int available = new FileInputStream(file).available();System.out.println("文件大小="+available);}}

实验10

理解多环境

  1. 准备一个类, 用来模拟数据库连接
package com.guigu.spring.ioc.datasource;@Data
public class MyDataSource {private String url;private String username;private String password;
}
  1. 通过配置类和环境注解, 创建数据库对象
package com.guigu.spring.ioc.config;//@Profile("dev") // 该注解也可以加载类上, 控制整体激活
@Configuration
public class DataSourceConfig {/*** 利用条件注解, 只在某种环境下激活一个组件* @Profile(环境标识) 当这个环境激活时, 才会加载这个组件* 使用:* 1.定义环境标识: 默认存在default标识, 我们自定义 dev test prop 三个标识* 2.激活环境标识: 告诉Spring当前处于什么环境, 默认时default环境*/@Profile("dev")@Beanpublic MyDataSource dev() {System.out.println("模拟dev环境连接数据库");MyDataSource dataSource = new MyDataSource();dataSource.setUrl("jdbc:mysql://localhost:3306/dev");dataSource.setUsername("dev_root");dataSource.setPassword("dev_root");return dataSource;}@Profile("test")@Beanpublic MyDataSource test() {System.out.println("模拟text环境连接数据库");MyDataSource dataSource = new MyDataSource();dataSource.setUrl("jdbc:mysql://localhost:3306/test");dataSource.setUsername("test_root");dataSource.setPassword("test_root");return dataSource;}@Profile("prod")@Beanpublic MyDataSource prod() {System.out.println("模拟prod环境连接数据库");MyDataSource dataSource = new MyDataSource();dataSource.setUrl("jdbc:mysql://localhost:3306/prod");dataSource.setUsername("prod_root");dataSource.setPassword("prod_root");return dataSource;}}
  1. 在配置文件中, 激活环境

spring.profiles.active=dev
  1. 运行代码, 不同环境下, 注入不同的数据库连接对象, 实现多环境
package com.guigu.spring.ioc;/*** 主入口文件*/
@SpringBootApplication
public class Spring01IocApplication {/*** 组件注入*/public static void main(String[] args) throws IOException {ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);}
}

实验11

使用原生spring的方式启动容器

package com.guigu.spring.ioc;/*** 主入口文件*/
@SpringBootApplication
public class Spring01IocApplication {/*** 使用原生方式启动容器*/public static void main(String[] args) {// SpringApplication这个类是boot包下的类, 其实是springboot提供的管理容器的类//ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);// 没有springboot之前, 是如何启动容起的呢?// 1.自己创建: 在类路径下找配置文件, 配置文件中声明需要的组件ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("classpath:ioc.xml");// 2.自己创建: 在其他盘中找配置文件// FileSystemXmlApplicationContext ioc = new FileSystemXmlApplicationContext("D:/");// 查看组件for (String definitionName : ioc.getBeanDefinitionNames()) {System.out.println("组件名称:"+ definitionName);}}
}

新建配置文件

<?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.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><!-- 声明默认值的组件: id是组件的唯一名称   --><bean id="zhngsan" class="com.guigu.spring.ioc.bean.Person"></bean><!-- 声明组件: 设置属性, 注意Person类中要提供set方法  --><bean id="lisi" class="com.guigu.spring.ioc.bean.Person"><property name="name" value="李四"></property><property name="age" value="#{10 + 10}"></property></bean><!-- 批量扫描   --><context:component-scan base-package="com.guigu.spring" /><!--导入属性文件 --><context:property-placeholder location="application.properties" />
</beans>

运行项目, 容器启动, 注册正常注册

http://www.xdnf.cn/news/400231.html

相关文章:

  • 【C++重载操作符与转换】构造函数和复制控制
  • 嵌入式培训之数据结构学习(一)数据结构的基础概念、线性表
  • 【AXI总线专题】AXI-FULL-Master
  • 具身-机器人-分层框架-大脑模块-RoboBrain1.0 RoboOS
  • AI大模型学习二十、利用Dify+deepseekR1 使用知识库搭建初中英语学习智能客服机器人
  • IBM BAW(原BPM升级版)使用教程第十二讲
  • ACL访问控制列表:access-list 10 permit 192.168.10.1
  • Matlab 模糊pid的液压舵机伺服系统
  • 重构金融数智化产业版图:中电金信“链主”之道
  • 【AI提示词】波特五力模型专家
  • Jenkins:库博静态工具CI/CD 的卓越之选
  • Pytorch常用统计和矩阵运算
  • 榜单按行显示
  • IP代理技术原理深度解析:从基础架构到应用实践
  • Open CASCADE学习|由大量Edge构建闭合Wire:有序与无序处理的完整解析
  • Matlab 基于GUI的汽车巡航模糊pid控制
  • STM32 变量存储
  • 深入浅出 iOS 对象模型:isa 指针 与 Swift Metadata
  • 生成对抗网络(GAN)深度解析:理论、技术与应用全景
  • SEGGER Embedded Studio 如何将其中的一个c文件 打包成静态库?
  • 最大m子段和
  • WebGL图形编程实战【6】:性能优化 × 调试工具与技巧精讲
  • (done) 补充:xv6 的一个用户程序 init 是怎么启动的 ?它如何启动第一个 bash ?
  • 模块化PCB设计中联排半孔的应用
  • 接口出现 请求参数格式错误 的解决方法
  • 使用 Navicat 将 Excel 导入数据库
  • C#WPF里不能出现滚动条的原因
  • geoserver发布arcgis瓦片地图服务(最新版本)
  • web 自动化之 Unittest 应用:报告装饰器断言
  • spring中的@PropertySource注解详解