11Spring IoC注解式开发(下)(负责注入的注解/全注解开发)

2024-01-14 08:12

本文主要是介绍11Spring IoC注解式开发(下)(负责注入的注解/全注解开发),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1负责注入的注解

负责注入的注解,常见的包括四个:

  • @Value
  • @Autowired
  • @Qualifier
  • @Resource

1.1 @Value

  • 当属性的类型是简单类型时,可以使用@Value注解进行注入。
  • @Value注解可以出现在属性上、setter方法上、以及构造方法的形参上, 方便起见,一般直接作用在属性上.
package com.sunsplanter.bean;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class User {@Value(value = "zhangsan")private String name;@Value("20")private int age;@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}
/*@Value和setter方法结合private String name;private int age;@Value("李四")public void setName(String name) {this.name = name;}@Value("30")public void setAge(int age) {this.age = age;}
*//*@Value和构造方法结合private String name;private int age;public User(@Value("隔壁老王") String name, @Value("33") int age) {this.name = name;this.age = age;}
*/
}

配置文件开启包扫描:

<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.sunsplanter.bean"/>
</beans>

测试程序:

@Test
public void testValue(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");Object user = applicationContext.getBean("user");System.out.println(user);
}

三种方法都可以正确注入简单类型.

1.2 @Autowired与@Qualifier

  • @Autowired注解可以用来注入非简单类型。被翻译为:自动连线的,或者自动装配。
  • @Autowired注解可以出现在构造方法上/方法上/形参上/属性上/注解
  • @Autowired注解有一个required属性,默认值是true,表示在注入的时候要求被注入的Bean必须是存在的,如果不存在则报错。如果required属性设置为false,表示注入的Bean存在或者不存在都没关系,存在的话就注入,不存在的话,也不报错。

目标: 存在两层: Service层和Dao层. 如前所述,UserService要控制UserDaoForMySQL, 必须要实例化一个UserDaoForMySQL的对象并注入到UserService类中定义的UserDaoForMySQL中.
配置Bean后Spring容器帮我们实例化了这个对象, 之前也学过了如何通过配置Bean标签注入. 本节的目标是通过注解完成自动注入.

结构为:
在这里插入图片描述

Dao层接口UserDao:

package com.dao;public interface UserDao {void insert();
}

实现类UserDaoForMySQL:

package com.dao;import org.springframework.stereotype.Repository;@Repository //纳入bean管理
public class UserDaoForMySQL implements UserDao{@Overridepublic void insert() {System.out.println("正在向mysql数据库插入User数据");}
}

Service层:

package com.Service;import com.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service // 纳入bean管理
public class UserService {@Autowired // 在属性上注入private UserDao userDao;// 没有提供构造方法和setter方法。public void save(){userDao.insert();}/* @Autowired和setter方法结合
private UserDao userDao;@Autowiredpublic void setUserDao(UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}*//*@Autowired和构造方法结合private UserDao userDao;public UserService(@Autowired UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}*/
}

配置文件开启包扫描:

<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.dao,com.service"/>
</beans>

测试程序:

@Test
public void testAutowired(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");UserService userService = applicationContext.getBean("userService", UserService.class);userService.save();
}

  • 单独使用@Autowired注解,默认根据类型装配【byType】。但之前也提到过,如果两个相同类型的类在同一包下,则系统分辨不出自动注解哪个bean, 例如:
    在这里插入图片描述
    两个bean类都实现了UserDao接口.无法分辨

解决办法:@Autowired注解和@Qualifier注解联合起来才可以根据名称进行装配,在@Qualifier注解中指定Bean名称。
将Service层代码增加一个@Qualifier注解,指定注入到userDaoForOracle:

private UserDao userDao;@Autowired@Qualifier("userDaoForOracle") // 这个是bean的名字。public void setUserDao(UserDao userDao) {this.userDao = userDao;}

1.3 @Resource

  • @Resource注解也可以完成非简单类型注入, 但与@AutoWired的区别如下
  • @Resource注解是JDK扩展包中的,也就是说属于JDK的一部分。所以该注解是标准注解,更加具有通用性。
    @Autowired注解是Spring框架自己的。
  • @Resource注解默认根据名称装配byName,未指定name时,使用属性名作为name。通过name找不到的话会自动启动通过类型byType装配。
    @Autowired注解默认根据类型装配byType,如果想根据名称装配,需要配合@Qualifier注解一起用。
  • @Resource注解用在属性上、setter方法上。
    @Autowired注解用在属性上、setter方法上、构造方法上、构造方法参数上。
  • @Resource注解属于JDK扩展包,所以不在JDK当中,需要额外引入以下依赖:【如果是JDK8的话不需要额外引入依赖。高于JDK11或低于JDK8需要引入以下依赖。】

Spring6不再支持JavaEE,它支持的是JakartaEE9。(之前所接触的所有的 javax.* 包名统一修改为 jakarta.*包名了。)
若使用Spring6, 引入:

<dependency><groupId>jakarta.annotation</groupId><artifactId>jakarta.annotation-api</artifactId><version>2.1.1</version>
</dependency>

使用:

UserDaoForOracle的名字为userDao,让这个Bean的名字和UserService类中的UserDao属性名一致:

package com.sunsplanter.dao;import org.springframework.stereotype.Repository;@Repository(value = "userDaoForOracle")
public class UserDaoForOracle implements UserDao{@Overridepublic void insert() {System.out.println("正在向Oracle数据库插入User数据");}
}
package com.sunsplanter.service;import com.sunsplanter.dao.UserDao;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;@Service
public class UserService {@Resource(name = "userDaoForOracle")private UserDao userDao;public void save(){userDao.insert();}
}

测试程序:

@Test
public void testResources(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");UserService userService = applicationContext.getBean("userService", UserService.class);userService.save();
}

以上代码使用Resource注解根据name(bean id)进行注入.Resource的的name(bean id为)userDaoForOracle,且注解写在UserDao头上.那么就去寻找一个名为userDaoForOracle的UserDao实现类进行注入.

2 全注解开发

尽管注解开发可以省略定义bean,但只能省略自定义的bean,若引入的是外部对象(如druid),此时依然要在xml中声明一个bean,由于此,不能完全消除配置xml文件的繁琐。

因此引入全注解开发(基于配置类的方式管理bean)
所谓的全注解开发就是不再使用spring配置文件spring.xml了。写一个配置类来代替配置文件. 其中配置类中使用
@configuration
@componentScan
等注解发挥spring.xml的作用

  1. 完全注解方式指的是去掉xml文件,使用配置类 + 注解实现
  2. xml文件替换成使用@Configuration注解标记的类
  3. 标记IoC注解:@Component,@Service,@Controller,@Repository
  4. 标记DI注解:@Autowired @Qualifier @Resource @Value
  5. <context:component-scan标签指定注解范围使用@ComponentScan(basePackages = {“com.atguigu.components”})替代
  6. <context:property-placeholder引入外部配置文件使用@PropertySource({“classpath:application.properties”,“classpath:jdbc.properties”})替代
  7. <bean 标签使用@Bean注解和方法实现
  8. IoC具体容器实现选择AnnotationConfigApplicationContext对象

在这里插入图片描述
对于上例, 新增一个配置类代替spring.xml,至于Service层的代码完全不变:

package com.sunsplanter.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;//标注当前类是配置类,替代spring.xml    
@Configuration
//使用注解读取外部配置,替代 <context:property-placeholder标签
@PropertySource("classpath:jdbc.properties")
//使用@ComponentScan注解,可以配置扫描包,替代<context:component-scan标签
@ComponentScan(basePackages = {"com.sunsplanter.service"})
public class Spring6Configuration {}
@Test
public void testNoXml(){
// AnnotationConfigApplicationContext 根据配置类创建 IOC 容器对象
//ClassPathXmlApplicationContext根据路径中的xml文件创建IOC容器对象ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Spring6Configuration.class);UserService userService = applicationContext.getBean("userService", UserService.class);userService.save();
}

在这里插入图片描述

2.1 将外部类纳入IoC容器管理

场景需求:将Druid连接池对象存储到IoC容器

需求分析:如开头所述:第三方jar包的类,添加到ioc容器,无法使用@Component等相关注解!因为源码jar包内容为只读模式!
思路:DataSource是JavaX中的一个接口,通过实现该接口来获取DataSource对象,将该方法声明为@Bean后,用value值注入创建datasource所需的各种属性。

package com.sunsplanter.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;//标注当前类是配置类,替代application.xml
@Configuration
//引入jdbc.properties文件
@PropertySource({"classpath:jdbc.properties"})
@ComponentScan(basePackages = {"com.sunsplanter"})
public class MyConfiguration {//如果第三方类进行IoC管理,无法直接使用@Component相关注解//解决方案: xml方式可以使用<bean标签//解决方案: 配置类方式,可以使用方法返回值+@Bean注解//DataSource是JavaX中的一个接口,通过实现该接口来获取DataSource对象@Beanpublic DataSource createDataSource(@Value("${jdbc.user}") String username,@Value("${jdbc.password}")String password,@Value("${jdbc.url}")String url,@Value("${jdbc.driver}")String driverClassName){//使用Java代码实例化//new出一个Druid连接池对象DruidDataSource dataSource = new DruidDataSource();//给该对象填上数据库参数后返回,今后需要用从外部调用dataSource即可//set方法是DataSource接口中预定义的抽象方法dataSource.setUsername(username);dataSource.setPassword(password);dataSource.setUrl(url);dataSource.setDriverClassName(driverClassName);//返回结果即可return dataSource;}
}

2.2 @import注解

**场景1:**将外部类纳入IoC管理

正常情况下,定义一个普通对象类,我们在类上声明为@Bean,今后再编写一个配置类configuration.java,类中配置扫描包,即可自动寻找到所有Bean并自动注入.

然而,一些外部类原作者编写的时候并不可能按我们心意提前写好@Bean注解,并且如2.1所述, 一些写好的外部类根本不允许我们修改. 但我们却仍想将这些外部类纳入IoC容器管理.(即自动生成对象, 自动注入,生命周期管理…)

此时就要用到@import。

  1. 自定义一个类 没有任何注解(模拟不能添加注解的外部类)
public class MyClass {public void test() {System.out.println("test方法");}
}

在配置类Configuration中 import这个myClass类

@configuration
@ComponentScan(basePackages = {"com.sunsplanter"})
public class Configuration{
@Import(MyClass.class)
public class Configuration {
}

测试程序为:

public void main(String[] args){ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Configuration.class);//我们已经首先根据配置类Configuration生成了上下文对象,并且在配置类我们声明了:外部类MyClass要纳入此上下文容器管理。//因此此时可以根据这个上下文对象getBean。MyClass myClass = applicationContext.getBean(MyClass.class);myClass.test();
}
}

情景2:存在多个配置类,简化生成上下文容器的流程

@Configuration
public class ConfigA {@Beanpublic A a() {return new A();}
}@Configuration
@Import(ConfigA.class)
public class ConfigB {@Beanpublic B b() {return new B();}
}

现在,在实例化上下文时不需要同时指定 ConfigA.class 和 ConfigB.class ,只需显式提供 ConfigB :

public static void main(String[] args) {ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);// now both beans A and B will be available...A a = ctx.getBean(A.class);B b = ctx.getBean(B.class);
}

这篇关于11Spring IoC注解式开发(下)(负责注入的注解/全注解开发)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/604497

相关文章

基于Python开发电脑定时关机工具

《基于Python开发电脑定时关机工具》这篇文章主要为大家详细介绍了如何基于Python开发一个电脑定时关机工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 简介2. 运行效果3. 相关源码1. 简介这个程序就像一个“忠实的管家”,帮你按时关掉电脑,而且全程不需要你多做

Spring核心思想之浅谈IoC容器与依赖倒置(DI)

《Spring核心思想之浅谈IoC容器与依赖倒置(DI)》文章介绍了Spring的IoC和DI机制,以及MyBatis的动态代理,通过注解和反射,Spring能够自动管理对象的创建和依赖注入,而MyB... 目录一、控制反转 IoC二、依赖倒置 DI1. 详细概念2. Spring 中 DI 的实现原理三、

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

SpringBoot使用注解集成Redis缓存的示例代码

《SpringBoot使用注解集成Redis缓存的示例代码》:本文主要介绍在SpringBoot中使用注解集成Redis缓存的步骤,包括添加依赖、创建相关配置类、需要缓存数据的类(Tes... 目录一、创建 Caching 配置类二、创建需要缓存数据的类三、测试方法Spring Boot 熟悉后,集成一个外

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

C#图表开发之Chart详解

《C#图表开发之Chart详解》C#中的Chart控件用于开发图表功能,具有Series和ChartArea两个重要属性,Series属性是SeriesCollection类型,包含多个Series对... 目录OverviChina编程ewSeries类总结OverviewC#中,开发图表功能的控件是Char

鸿蒙开发搭建flutter适配的开发环境

《鸿蒙开发搭建flutter适配的开发环境》文章详细介绍了在Windows系统上如何创建和运行鸿蒙Flutter项目,包括使用flutterdoctor检测环境、创建项目、编译HAP包以及在真机上运... 目录环境搭建创建运行项目打包项目总结环境搭建1.安装 DevEco Studio NEXT IDE

Python开发围棋游戏的实例代码(实现全部功能)

《Python开发围棋游戏的实例代码(实现全部功能)》围棋是一种古老而复杂的策略棋类游戏,起源于中国,已有超过2500年的历史,本文介绍了如何用Python开发一个简单的围棋游戏,实例代码涵盖了游戏的... 目录1. 围棋游戏概述1.1 游戏规则1.2 游戏设计思路2. 环境准备3. 创建棋盘3.1 棋盘类

使用@Slf4j注解,log.info()无法使用问题

《使用@Slf4j注解,log.info()无法使用问题》在使用Lombok的@Slf4j注解打印日志时遇到问题,通过降低Lombok版本(从1.18.x降至1.16.10)解决了问题... 目录@Slf4androidj注解,log.info()无法使用问题最后解决总结@Slf4j注解,log.info(