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;

    @Override
    public 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.xsd
                           http://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{
    @Override
    public 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;

    @Autowired
    public 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.xsd
                           http://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{
    @Override
    public 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对象
    @Bean
    public 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 {

  @Bean
  public A a() {
    return new A();
  }
}

@Configuration
@Import(ConfigA.class)
public class ConfigB {

  @Bean
  public 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);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【 ATU 随笔记 - Inverter 】PV Inverter 太阳能逆变器市场分析

一、简介 在上一篇的介绍中与大家分享了Micro Inverter ( 微型逆变器 )的用途与特色&#xff0c;也提到 Micro Inverter 适合家庭或是一些小型企业的需求。太阳能作为再生能源的代表&#xff0c;在当今能源转型中扮演着重要角色&#xff0c;也是有大型企业、大型能源站的需求&a…

Java项目:06 Springboot的进销存管理系统

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 进销存管理系统 介绍 进销存系统是为了对企业生产经营中进货、出货、批发销售、付款等全程进行&#xff08;从接获订单合同开 始&#xff0c;进入物料采购、入…

杨中科 .NETCORE ENTITY FRAMEWORK CORE-1 EFCORE 第一部分

一 、什么是EF Core 什么是ORM 1、说明: 本课程需要你有数据库、SOL等基础知识。 2、ORM: ObjectRelational Mapping。让开发者用对象操作的形式操作关系数据库 比如插入: User user new User(Name"admin"Password"123”; orm.Save(user);比如查询: Book b…

计算机三级(网络技术)一综合题(IP地址计算)

例题一 &#xff08;正常算&#xff09; 计算并填写下表 地址类别 A类地址段是1.0.0.0~127.255.255.255 1~127 B类地址段是128.0.0.0~191.255.255.255 128~191 C类地址段是192.0.0.0~223.255.255.255 192~223 所以41填A 网络地址为主机位全0 根据子网掩码&…

Redis实现分布式会话

Redis实现分布式会话 1 什么是分布式会话 1 这是我么之前学过的注册登录模式 2 如果非常多的人访问&#xff0c;因为单台服务器的访问承受能力是有限的&#xff0c;那么我们就想用多态服务器来承担压力 3 一般通过负载均衡的方式来实现&#xff0c;来分担服务器的压力。 4 负…

【Redis】Redis数据过期策略、数据淘汰策略

数据过期策略 首先&#xff0c;我们要知道Redis的数据过期策略是惰性删除和定期删除结合使用。 面试题&#xff1a; 惰性删除 定期删除 数据淘汰策略 Redis支持8种数据淘汰策略&#xff1a; noeviction&#xff1a;不淘汰任何key&#xff0c;当内存满时&#xff0c;不写入任何…

TCP之三次握手四次挥手与UDP区别

文章目录 1 TCP三次握手四次挥手1.1 数据包说明1.1.1 TCP数据包1.1.2 UDP数据包1.1.3 TCP和UDP差异1.1.4 TCP可靠性传输机制 1.2 三次握手1.2.1 三次握手定义1.2.2 三次握手问题1.2.2.1 问题引入分析1.2.2.2 历史连接1.2.2.3 同步双方初始序列号1.2.2.4 避免资源浪费 1.3 四次挥…

POSTGRESQL中ETL、fdw的平行替换

POSTGRESQL中ETL、fdw的平行替换 01、简介 “ 在我前两次的文章中&#xff0c;说到postgresql对于python的支持&#xff0c;其实很多功能也就可以封装进入的postgresql数据库中去。比如fdw、etl等&#xff0c;本文将以此为叙述点&#xff0c;进行演示展示” 在postgresql数据…

详解矩阵变换:伸缩,旋转,反射和投影

目录 一. 矩阵子空间 二. 矩阵变换 2.1 伸缩矩阵 2.2 旋转矩阵 2.3 反射矩阵 2.4 投影矩阵 2.5 小结 三. 矩阵变换与函数 3.1 原点 3.2 常数倍性质 3.3 加法性质 3.4 小结 四. 空间变换 五. 小结 一. 矩阵子空间 矩阵与向量相乘Ax可以看成子空间的变换。 零空间…

一文搞定,JMeter的三种参数化方式

1、Test Plan 中添加变量 可以在 Test Plan 中设置好添加变量&#xff0c;变量名可以在任意的位置使用&#xff0c;比如说在线程组中直接用${ 变量名 }方式引用&#xff0c;步骤如下&#xff1a; 1&#xff09;设置变量名和变量值 2&#xff09;添加线程组 3&#xff09;添加…

[情商-11]:人际交流的心理架构与需求层次模型

目录 前言&#xff1a; 一、心理架构 1.1 个体生理层 1.2 个体心理层 1.3 点对点人际交流层 1.4 社会网络层 1.5 社会价值层 二、人的需求层次模型 2.1 需求&#xff08;欲望&#xff09;层次模型 2.2 基因与人需求之间的关系 2.3 个体生理需求 2.4 个体的心理需求…

MyBatis源码分析(六):数据源模块

1. 概述 本文&#xff0c;我们来分享 MyBatis 的数据源模块&#xff0c;对应 datasource 包。如下图所示&#xff1a; ​ 在 MyBatis源码分析&#xff08;二&#xff09;&#xff1a;项目结构 中&#xff0c;简单介绍了这个模块如下&#xff1a; 数据源是实际开发中常用的组件…

5 微信小程序

功能开发 5 功能开发概要今日详细1.发布1.1 发布流程的问题1.2 组件&#xff1a;进度条1.3 修改data中的局部数据1.4 发布示例效果前端后端 1.5 闭包 2.获取前10条新闻&#xff08;动态/心情&#xff0c;无需分页&#xff09;3.复杂版4.文章详细页面 各位小伙伴想要博客相关资料…

Java--业务场景:SpringBoot 通过Redis进行IP封禁实现接口防刷

文章目录 前言具体实现步骤1. 定义自定义注解2. 编写拦截器类IpUrlLimitInterceptor3. 在WebConfig类中添加IpUrlLimitInterceptor4. 添加注解到接口上 测试效果参考文章 前言 在实际项目中&#xff0c;有些攻击者会使用自动化工具来频繁刷新接口&#xff0c;造成系统的瞬时吞…

一些前端学习过程的自测练习题

目录 页面设计部分 1 设计一个简单的学院网站首页&#xff1b; 2.按照图示要求完成简单的登录页面 3.完成如下网站设计 4.完成如下网站设计&#xff08;练习页面布局&#xff09; 5 利用下面素材&#xff0c;设计一个满足H5规范的网页&#xff08;移动端页面练习&#xff…

leetcode刷题记录18(2023-08-29)【最短无序连续子数组(单调栈) | 合并二叉树(dfs) | 任务调度器(桶) | 回文子串(二维dp)】

581. 最短无序连续子数组 给你一个整数数组 nums &#xff0c;你需要找出一个 连续子数组 &#xff0c;如果对这个子数组进行升序排序&#xff0c;那么整个数组都会变为升序排序。 请你找出符合题意的 最短 子数组&#xff0c;并输出它的长度。 示例 1&#xff1a; 输入&am…

TensorRT模型优化模型部署(七)--Quantization量化(PTQ and QAT)(二)

系列文章目录 第一章 TensorRT优化部署&#xff08;一&#xff09;–TensorRT和ONNX基础 第二章 TensorRT优化部署&#xff08;二&#xff09;–剖析ONNX架构 第三章 TensorRT优化部署&#xff08;三&#xff09;–ONNX注册算子 第四章 TensorRT模型优化部署&#xff08;四&am…

Java中finally和return的执行顺序

Java中finally和return的执行顺序 try...catch...finally1. finally语句在return语句执行之后return返回之前执行的2. finally块中的return语句会覆盖try块中的return返回3. 如果finally语句中没有return语句覆盖返回值&#xff0c;那么原来的返回值可能因为finally里的修改而改…

进程的状态

进程状态反映进程执行过程的变化。这些状态随着进程的执行和外界条件的变化而转换。在三态模型 中&#xff0c;进程状态分为三个基本状态&#xff0c;即就绪态&#xff0c;运行态&#xff0c;阻塞态。在五态模型中&#xff0c;进程分为新建态、就绪态&#xff0c;运行态&#x…

【书生·浦语】大模型实战营——第四课笔记

教程链接&#xff1a;https://github.com/InternLM/tutorial/blob/main/xtuner/README.md 视频链接&#xff1a;https://www.bilibili.com/video/BV1yK4y1B75J/?vd_source5d94ee72ede352cb2dfc19e4694f7622 本次视频的内容分为以下四部分&#xff1a; 目录 微调简介 微调会使…