【精选】SpringDI依赖注入及注解实现SpringIoC

SpringDI

请添加图片描述

什么是依赖注入

在这里插入图片描述

依赖注入(Dependency Injection,简称DI),它是Spring控制反转思想的具体实现。

控制反转将对象的创建交给了Spring,但是对象中可能会依赖其他对象。比如service类中要有dao类的属性,我们称service依赖于dao。之前需要手动注入属性值,代码如下:

public interface StudentDao {Student findById(int id);
}public class StudentDaoImpl implements StudentDao{@Overridepublic Student findById(int id) {// 模拟根据id查询学生return new Student(1,"张三","北京");}
}public class StudentService {// service依赖dao,手动注入属性值,即手动维护依赖关系private StudentDao studentDao = new StudentDaoImpl();public Student findStudentById(int id){return studentDao.findById(id);}
}

此时,当StudentService的想要使用StudentDao的另一个实现类如StudentDaoImpl2时,则需要修改Java源码,造成代码的可维护性降低。

而使用Spring框架后,Spring管理Service对象与Dao对象,此时它能够为Service对象注入依赖的Dao属性值。这就是Spring的依赖注入。简单来说,控制反转是创建对象,依赖注入是为对象的属性赋值。

依赖注入方式

在这里插入图片描述

在之前开发中,可以通过setter方法或构造方法设置对象属性值:

// setter方法设置属性
StudentService studentService = new StudentService();
StudentDao studentDao = new StudentDao();
studentService.setStudentDao(studentDao);// 构造方法设置属性
StudentDao studentDao = new StudentDao();
StudentService studentService = new StudentService(studentDao);

Spring可以通过调用setter方法或构造方法给属性赋值

Setter注入
  1. 被注入类编写属性的setter方法

    public class StudentService {private StudentDao studentDao;public void setStudentDao(StudentDao studentDao) {this.studentDao = studentDao;}
    }
    
  2. 配置文件中,给需要注入属性值的<bean>中设置<property>

    <bean id="studentDao" class="com.Spring.dao.StudentDaoImpl"></bean>
    <bean id="studentService" class="com.Spring.service.StudentService"><!--依赖注入--><!--name:对象的属性名 ref:容器中对象的id值--><property name="studentDao" ref="studentDao"></property>
    </bean>
    
  3. 测试是否注入成功

    @Test
    public void t2(){ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");StudentService studentService = (StudentService) ac.getBean("studentService");System.out.println(studentService.findStudentById(1));
    }
    
构造方法注入
  1. 被注入类编写有参的构造方法

    public class StudentService {private StudentDao studentDao;public StudentService(StudentDao studentDao) {this.studentDao = studentDao;}
    }
    
  2. 给需要注入属性值的<bean>中设置<constructor-arg>

    <bean id="studentDao" class="com.Spring.dao.StudentDaoImpl"></bean><bean id="studentService" class="com.Spring.service.StudentService"><!-- 依赖注入 --><!-- name:对象的属性名  ref:配置文件中注入对象的id值 --><constructor-arg name="studentDao" ref="studentDao"></constructor-arg>
    </bean>
    
  3. 测试是否注入成功

    @Test
    public void t2(){ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");StudentService studentService = (StudentService) ac.getBean("studentService");System.out.println(studentService.findStudentById(1));
    }
    
自动注入

自动注入不需要在<bean>标签中添加其他标签注入属性值,而是自动从容器中找到相应的bean对象设置为属性值。

自动注入有两种配置方式:

  • 全局配置:在<beans>中设置default-autowire属性可以定义所有bean对象的自动注入策略。
  • 局部配置:在<bean>中设置autowire属性可以定义当前bean对象的自动注入策略。

autowire的取值如下:

  • no:不会进行自动注入。
  • default:全局配置default相当于no,局部配置default表示使用全局配置
  • byName:在Spring容器中查找id与属性名相同的bean,并进行注入。需要提供set方法。
  • byType:在Spring容器中查找类型与属性类型相同的bean,并进行注入。需要提供set方法。
  • constructor:在Spring容器中查找id与属性名相同的bean,并进行注入。需要提供构造方法。

测试自动注入:

  1. 为依赖的对象提供setter和构造方法:

    public class StudentService {// 依赖private StudentDao studentDao;// 构造方法public StudentService() {}public StudentService(StudentDao studentDao) {this.studentDao = studentDao;}// setter方法public void setStudentDao(StudentDao studentDao) {this.studentDao = studentDao;}// 调用依赖的方法public Student findStudentById(int id) {return studentDao.findById(id);}
    }
  2. 配置自动注入:

    <!-- 根据beanId等于属性名自动注入 -->
    <bean id="studentDao" class="com.Spring.dao.StudentDaoImpl"></bean>
    <bean id="studentService" class="com.Spring.service.StudentService" autowire="byName"></bean>
    <!-- 根据bean类型等于属性类型自动注入 -->
    <bean id="studentDao" class="com.Spring.dao.StudentDaoImpl"></bean>
    <bean id="studentService" class="com.Spring.service.StudentService" autowire="byType"></bean>
    <!-- 利用构造方法自动注入 -->
    <bean id="studentDao" class="com.Spring.dao.StudentDaoImpl"></bean>
    <bean id="studentService" class="com.Spring.service.StudentService" autowire="constructor"></bean>
    
    <!-- 配置全局自动注入 -->
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"default-autowire="constructor">

依赖注入类型

DI支持注入bean类型、基本数据类型和字符串、List集合、Set集合、Map集合、Properties对象类型等,他们的写法如下:

  1. 准备注入属性的类

    public class StudentService {private StudentDao studentDao; // bean属性private String name; //字符串类型private int count; //基本数据类型private List<String> names; // 字符串类型List集合private List<Student> students1; // 对象类型List集合private Set<Student> students2; // 对象类型Set集合private Map<String,String> names2; // 字符串类型Map集合private Map<String,Student> students3; // 对象类型Map集合private Properties properties; //Properties类型// 省略getter/setter/toString
    }
  2. 准备测试方法

    @Test
    public void t3(){ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");StudentService studentService = (StudentService) ac.getBean("studentService");System.out.println(studentService);
    }
注入bean类型

写法一:

<bean id="studentDao" class="com.Spring.dao.StudentDaoImpl"></bean><bean id="studentService" class="com.Spring.service.StudentService"><property name="studentDao" ref="studentDao"></property>
</bean>

写法二:

<bean id="studentDao" class="com.Spring.dao.StudentDaoImpl"></bean><bean id="studentService" class="com.Spring.service.StudentService"><property name="studentDao" ><ref bean="studentDao"></ref></property>
</bean>
注入基本数据类型和字符串类型
<bean id="studentService" class="com.Spring.service.StudentService"><!--  写法一 name:属性名  value:属性值--><property name="name" value="李四"></property><!--  写法二 name:属性名  value:属性值--><property name="count"><value>10</value></property>
</bean>
注入List集合
<bean id="studentService" class="com.Spring.service.StudentService"><!-- 简单数据类型List集合 name:属性名 --><property name="names"><list><value>Spring</value><value>张三</value></list></property><!-- 对象类型List集合 name:属性名 --><property name="students1"><list><bean class="com.Spring.domain.Student"><property name="id" value="1"/><property name="name" value="Spring"/><property name="address" value="北京"/></bean><bean class="com.Spring.domain.Student"><property name="id" value="2"/><property name="name" value="李四"/><property name="address" value="北京"/></bean></list></property>
</bean>
注入Set集合
<bean id="studentService" class="com.Spring.service.StudentService"><!-- Set集合 --><property name="students2"><set><bean class="com.Spring.domain.Student"><property name="id" value="1"/><property name="name" value="Spring"/><property name="address" value="北京"/></bean><bean class="com.Spring.domain.Student"><property name="id" value="2"/><property name="name" value="李四"/><property name="address" value="北京"/></bean></set></property>
</bean>
注入Map集合

简单数据类型Map集合:

<bean id="studentService" class="com.Spring.service.StudentService"><property name="names2"><map><entry key="student1" value="李四"/><entry key="student2" value="张三"/></map></property>
</bean>

对象类型Map集合:

<bean id="studentService" class="com.Spring.service.StudentService"><property name="students3"><map><entry key="student1" value-ref="s1"/><entry key="student2" value-ref="s2"/></map></property>
</bean><bean id="s1" class="com.Spring.domain.Student"><property name="id" value="1"/><property name="name" value="Spring"/><property name="address" value="北京"/>
</bean>
<bean id="s2" class="com.Spring.domain.Student"><property name="id" value="2"/><property name="name" value="李四"/><property name="address" value="北京"/>
</bean>
注入Properties对象
<bean id="studentService" class="com.Spring.service.StudentService"><property name="properties"><props><prop key="配置1">值1</prop><prop key="配置2">值2</prop></props></property>
</bean>

注解实现IOC

准备工作

注解配置和xml配置对于Spring的IOC要实现的功能都是一样的,只是配置的形式不一样。

准备工作

  1. 创建一个新的Spring项目。

  2. 编写pojo,dao,service类。

  3. 编写空的配置文件,如果想让该文件支持注解,需要添加新的约束

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://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"></beans>

@Component

作用:用于创建对象,放入Spring容器,相当于<bean id="" class="">

位置:类上方

注意:

  • 要在配置文件中配置扫描的包,扫描到该注解才能生效。

    <context:component-scan base-package="com.Spring"></context:component-scan>
    
  • @Component注解配置bean的默认id是首字母小写的类名。也可以手动设置bean的id值。

    // 此时bean的id为studentDaoImpl
    @Component
    public class StudentDaoImpl implements StudentDao{public Student findById(int id) {// 模拟根据id查询学生return new Student(1,"张三","北京");}
    }
    

    // 此时bean的id为studentDao
    @Component(“studentDao”)
    public class StudentDaoImpl implements StudentDao{
    public Student findById(int id) {
    // 模拟根据id查询学生
    return new Student(1,“张三”,“北京”);
    }
    }

    
    

@Repository、@Service、@Controller

作用:这三个注解和@Component的作用一样,使用它们是为了区分该类属于什么层。

位置:

  • @Repository用于Dao层
  • @Service用于Service层
  • @Controller用于Controller层
@Repository
public class StudentDaoImpl implements StudentDao{}@Service
public class StudentService {}

@Scope

作用:指定bean的创建策略

位置:类上方

取值:singleton prototype request session globalsession

@Service
@Scope("singleton")
public class StudentService {}

@Autowired

作用:从容器中查找符合属性类型的对象自动注入属性中。用于代替<bean>中的依赖注入配置。

位置:属性上方、setter方法上方、构造方法上方。

注意:

  1. @Autowired写在属性上方进行依赖注入时,可以省略setter方法。

    @Component
    public class StudentService {@Autowiredprivate StudentDao studentDao;public Student findStudentById(int id){return studentDao.findById(id);}
    }@Test
    public void t2(){ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");StudentService studentService = (StudentService) ac.getBean("studentService");System.out.println(studentService.findStudentById(1));
    }
    
  2. 容器中没有对应类型的对象会报错

    // 如果StudentDaoImpl没有放到容器中会报错
    //@Component("studentDao")
    public class StudentDaoImpl implements StudentDao{public Student findById(int id) {// 模拟根据id查询学生return new Student(1,"张三","北京");}
    }
    
  3. 容器中有多个对象匹配类型时,会找beanId等于属性名的对象,找不到会报错。

    // 如果容器中都多个同类型对象,会根据id值等于属性名找对象
    @Component("studentDao")
    public class StudentDaoImpl implements StudentDao{public Student findById(int id) {// 模拟根据id查询学生return new Student(1,"张三","北京");}
    }@Component
    public class StudentDaoImpl2 implements StudentDao{public Student findById(int id) {// 模拟根据id查询学生return new Student(1,"张三","北京");}
    }
    

@Qualifier

作用:在按照类型注入对象的基础上,再按照bean的id注入。

位置:属性上方

注意:@Qualifier必须和@Autowired一起使用。

@Component
public class StudentService {@Autowired@Qualifier("studentDaoImpl2")private StudentDao studentDao;public Student findStudentById(int id){return studentDao.findById(id);}
}

@Value

作用:注入String类型和基本数据类型的属性值。

位置:属性上方

用法:

  1. 直接设置固定的属性值

    @Service
    public class StudentService {@Value("1")private int count;@Value("hello")private String str;
    }
  2. 获取配置文件中的属性值:

    1. 编写配置文件db.properties

      jdbc.username=root
      jdbc.password=123456
      
    2. spring核心配置文件扫描配置文件

      <context:property-placeholder location="db.properties"></context:property-placeholder>
      
    3. 注入配置文件中的属性值

      @Value("${jdbc.username}")
      private String username;@Value("${jdbc.password}")
      private String password;
      

@Configuration

此时基于注解的IOC配置已经完成,但是我们依然离不开Spring的xml配置文件。接下来我们脱离bean.xml,使用纯注解实现IOC。

在真实开发中,我们一般还是会保留xml配置文件,很多情况下使用配置文件更加方便。

纯注解实现IOC需要一个==Java类代替xml文件。==这个Java类上方需要添加@Configuration,表示该类是一个配置类,作用是代替配置文件。

@Configuration
public class SpringConfig {  
}

@ComponentScan

作用:指定spring在初始化容器时扫描的包。

位置:配置类上方

@Configuration
@ComponentScan("com.Spring")
public class SpringConfig {
}

@PropertySource

作用:代替配置文件中的<context:property-placeholder>扫描配置文件

位置:配置类上方

注意:配置文件位置前要加关键字classpath

@Configuration
@PropertySource("classpath:db.properties")
public class JdbcConfig {@Value("${jdbc.username}")private String username;@Value("${jdbc.password}")private String password;}

@Bean

作用:将方法的返回值对象放入Spring容器中。如果想将第三方类的对象放入容器,可以使用@Bean

位置:配置类的==方法==上方。

属性:name:给bean对象设置id

注意:@Bean修饰的方法如果有参数,spring会根据参数类型从容器中查找可用对象。

举例:如果想将jdbc连接对象放入Spring容器,我们无法修改Connection源码添加@Component,此时就需要使用将@Bean该对象放入Spring容器

  1. 添加驱动依赖

    <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version>
    </dependency>
    
  2. 将Connection对象放入Spring容器

    @Bean(name = "connection")
    public Connection getConnection(){try {Class.forName("com.mysql.cj.jdbc.Driver");return DriverManager.getConnection("jdbc:mysql:///mysql", "root", "root");} catch (Exception exception) {return null;}
    }
    
  3. 测试

    @Test
    public void t5(){ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);Connection connection = (Connection) ac.getBean("connection");System.out.println(connection);
    }
    

@Import

作用:如果配置过多,会有多个配置类,该注解可以为主配置类导入其他配置类

位置:主配置类上方

// Jdbc配置类
@Configuration
public class JdbcConfig {@Bean(name = "connection")public Connection getConnection(){try {Class.forName("com.mysql.cj.jdbc.Driver");return DriverManager.getConnection("jdbc:mysql:///mysql", "root", "root");} catch (Exception exception) {return null;}}
}// 主配置类
@Configuration
@ComponentScan("com.Spring")
@Import(JdbcConfig.class)
public class SpringConfig {
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VBA高级应用30例:Ribbon(功能区)的介绍

《VBA高级应用30例》&#xff08;版权10178985&#xff09;&#xff0c;是我推出的第十套教程&#xff0c;教程是专门针对高级学员在学习VBA过程中提高路途上的案例展开&#xff0c;这套教程案例与理论结合&#xff0c;紧贴“实战”&#xff0c;并做“战术总结”&#xff0c;以…

Nginx性能调优策略

Nginx是一个高性能的Web服务器和反向代理服务器&#xff0c;常用于处理高并发的请求。以下是一些常见的Nginx性能调优策略&#xff1a; 一、调整worker_processes和worker_connections 在Nginx配置文件中&#xff0c;可以通过worker_processes和worker_connections参数来调整w…

JAVA将PDF转图片

前言 当今时代&#xff0c;PDF 文件已经成为了常用的文档格式。然而&#xff0c;在某些情况下&#xff0c;我们可能需要将 PDF 文件转换为图片格式&#xff0c;以便更方便地分享和使用。这时&#xff0c;我们可以使用 Java 编程语言来实现这个功能。Java 提供了许多库和工具&a…

城市安全守护者:分析无人机在交通领域的应用

随着科技的进步&#xff0c;无人机在交通领域的应用不断增加&#xff0c;为智慧交通管理提供了新便利。无人机凭借其灵活性&#xff0c;在违章取证、交通事故侦查、交通疏导等方面展现出巨大的应用潜力。无人机在交通领域的应用有哪些&#xff1f;跟着我们一探究竟。 1、违章取…

系列二十四、Spring设计模式之策略模式

一、前言 对于我们Java开发人员来说&#xff0c;Spring框架的重要性不言而喻&#xff0c;可以说Java领域之所以发展这么壮大&#xff0c;生态这么丰富&#xff0c;功能这么强大&#xff0c;是离不开Spring以及由其衍生出来的各种子模块的&#xff0c;正是由它们共同奠定了JavaE…

ECShop 4.x collection_listSQL注入

漏洞描述 ECShop是一款B2C独立网店系统&#xff0c;适合企业及个人快速构建个性化网上商店。系统是基于PHP语言及MYSQL数据库构架开发的跨平台开源程序 影响版本&#xff1a;ecshop4.0.7及以下 漏洞环境及利用 docker环境搭建 访问8080端口&#xff0c;数据库主机为mysql&a…

如何确定先做哪件事情。

问题描述&#xff1a;工作或者生活中&#xff0c;有许多件事情&#xff0c;我们应该先做那件事情。 解决办法&#xff1a;重要紧急的四象限法则。具体如下所示&#xff1a; -----------------------------------------------------------------------------------------------…

基于OGG实现MySQL实时同步

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

海外ASO优化之如何优化应用程序预览

应用程序预览是演示应用的特性、功能的界面。通过简短视频吸引用户应用商店。由于应用程序预览自动播放&#xff0c;所以它们是帮助用户发现和了解我们应用的关键。 1、规划应用程序预览。 应用商店支持的多种语言&#xff0c;最多可以有三个应用预览&#xff0c;每个预览的时…

接口测试:Jmeter和Postman测试方法对比

前阶段做了一个小调查&#xff0c;发现软件测试行业做功能测试和接口测试的人相对比较多。在测试工作中&#xff0c;有高手&#xff0c;自然也会有小白&#xff0c;但有一点我们无法否认&#xff0c;就是每一个高手都是从小白开始的&#xff0c;所以今天我们就来谈谈一大部分人…

【C/PTA —— 12.指针1(课内实践)】

C/PTA —— 12.指针1&#xff08;课内实践&#xff09; 6-1 交换两个整数的值6-2 利用指针找最大值6-3 字符串的连接6-4 移动字母 6-1 交换两个整数的值 void fun(int* a, int* b) {int* tmp *a;*a *b;*b tmp; }6-2 利用指针找最大值 void findmax(int* px, int* py, int* p…

超声波雪深监测站冬季雪景的智能守护者

随着冬季的到来&#xff0c;白雪皑皑的景象让人感到无比美丽。然而&#xff0c;雪景的美丽却给人们的生活和出行带来了一定的困扰。雪的深度和分布是影响道路交通、公共安全和旅游体验的关键因素。为了解决这一问题&#xff0c;WX-XS1 超声波雪深监测站在冬季应运而生&#xff…

DjiTello + YoloV5的无人机的抽烟检测

一、效果展示 注&#xff1a;此项目纯作者自己原创&#xff0c;创作不易&#xff0c;不经同意不给予搬运权限&#xff0c;转发前请联系我&#xff0c;源码较大需要者评论获取&#xff0c;谢谢配合&#xff01; 1、未启动飞行模型无人机的目标检测。 DjiTello YOLOV5抽烟检测 …

【自然语言处理】利用sklearn库函数绘制三维瑞士卷

一&#xff0c;原理介绍 sklearn.datasets.make_swiss_roll&#xff08;&#xff09;函数提供了三维瑞士卷的数据集&#xff0c;我们可以利用他来生成瑞士卷&#xff0c;该函数的用法见sklearn官方文档&#xff1a;官网文档&#xff1a;sklearn.datasets.make_swiss_roll&…

语音机器人的两种常见业务场景

第一个业务场景 之前写过一篇语音机器人是真人录音好&#xff0c;还是TTS转语音更好的文章。今天再来说一说TTS一个很细微的场景。 假设一句话 这里是*****银行委托机构&#xff0c;您在*****银行的信用卡长期逾期至今仍未依照约定履行还款义务&#xff0c;为避免逃废债给您…

【bmp文件怎么批量改成JPG?】

操作 在需要修改格式的图片文件夹中新建一个TXT文本文档 文档中输入(ren *.原图片类型 *.需要修改成的图片类型) ren *.bmp *.jpg 输入完成后保存 将刚刚新建的文档重命名 修改为.bat后缀的文件 弹出弹窗&#xff0c;点击是 双击此程序&#xff0c;即可将文件夹中的BMP图…

RT-DETR改进 | 2023 | InnerEIoU、InnerSIoU、InnerWIoU、InnerDIoU等二十余种损失函数

论文地址&#xff1a;官方Inner-IoU论文地址点击即可跳转 官方代码地址&#xff1a;官方代码地址-官方只放出了两种结合方式CIoU、SIoU 本位改进地址&#xff1a; 文末提供完整代码块-包括InnerEIoU、InnerCIoU、InnerDIoU等七种结合方式和其AlphaIoU变种结合起来可以达到二十…

将用户的session改为分布式共享session

将用户的session改为分布式session 分布式session理解 使用分布式session的原因&#xff1a; 后台服务器是分布式的&#xff08;比如要负载均衡&#xff09;&#xff0c;在A服务器请求的的信息&#xff08;如用户登录信息&#xff09;存在A的session中&#xff0c;B服务器并不…

百度手机浏览器关键词排名优化——提升关键词排名 开源百度小程序源码系统 附带完整的搭建教程

百度作为国内领先的搜索引擎&#xff0c;一直致力于为用户提供最优质的信息服务。在移动互联网时代&#xff0c;手机浏览器成为了用户获取信息的主要渠道。而小程序作为轻量级的应用程序&#xff0c;具有即用即走、无需下载等优势&#xff0c;越来越受到用户的青睐。然而&#…