Spring-2-深入理解Spring 注解依赖注入(DI):简化Java应用程序开发

今日目标

掌握纯注解开发依赖注入(DI)模式

学习使用纯注解进行第三方Bean注入

1 注解开发依赖注入(DI)【重点】

问题导入

思考:如何使用注解方式将Bean对象注入到类中

1.1 使用@Autowired注解开启自动装配模式(按类型)

复制代码
@Service
public class StudentServiceImpl implements StudentService {

    //创建成员对象
    //@Autowired:注入引用类型,自动装配模式,默认按类型装配
    @Autowired
    private StudentDao studentDao ;

    @Override
    public void save() {
        System.out.println("Service: 添加学生信息到数据库...");
        studentDao.save();
    }
}

说明:不管是使用配置文件还是配置类,都必须进行对应的Spring注解包扫描才可以使用。@Autowired默认按照类型自动装配,如果IoC容器中同类的Bean有多个,那么默认按照变量名和Bean的名称匹配,建议使用@Qualifier注解指定要装配的bean名称

注意:自动装配基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据,因此无需提供setter方法。

1.2 使用@Qualifier注解指定要装配的bean名称

目的:解决IoC容器中同类型Bean有多个装配哪一个的问题

复制代码
@Service
public class StudentServiceImpl implements StudentService {

    //创建成员对象
    //@Autowired:注入引用类型,自动装配模式,默认按类型装配
    @Autowired
    //@Qualifier:自动装配bean时按bean名称装配
    @Qualifier("studentDaoImpl")
    private StudentDao studentDao ;

    @Override
    public void save() {
        System.out.println("Service: 添加学生信息到数据库...");
        studentDao.save();
    }
}

注意:@Qualifier注解无法单独使用,必须配合@Autowired注解使用

1.3 使用@Value实现简单类型注入

复制代码
@Repository
public class StudentDaoImpl implements StudentDao {

    //@Value:注入简单类型(无需提供set方法)
    @Value("${test.name}")
    private String name;
    @Override
    public void save() {
        System.out.println("DAO: name= "+name);
        System.out.println("DAO: 添加学生信息到数据库...");
    }
}

以上@Value注解中使用${test.name}从属性文件中读取test.name值,那么就需要在配置类或者配置文件中加载属性文件。

复制代码
@Configuration
@ComponentScan("com.itheima")
//@PropertySource加载properties配置文件
@PropertySource("classpath:test.properties") //如果是多个属性文件,则使用{}数组
public class SpringConfig {
}

注意:@PropertySource中加载多文件请使用数组格式配置,不允许使用通配符*

2 注解开发管理第三方Bean【重点】

问题导入

思考:导入自己定义的配置类有几种方式?

【第零步】pom.xml添加数据库依赖

复制代码
<!-- mysql 驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
</dependency>
<!--druid包-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.18</version>
</dependency>

【第一步】单独定义配置类在config包下创建

复制代码
package com.zbbmeta.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;

public class JdbcConfig {
    //@Bean:表示当前方法的返回值是一个bean对象,添加到IOC容器中
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_druid");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

【第二步】将独立的配置类加入核心配置

方式1:@Import注解导入式

复制代码
@Configuration // 指定这个类为配置类,替代application.xml
@ComponentScan("com.zbbmeta")//代替<context:component-scan base-package="com.zbbmeta" />
@PropertySource("classpath:test.properties") //如果是多个属性文件,则使用{}数组
@Import(JdbcConfig.class)  //加载JdbcConfig配置类
public class SpringConfig {


}

方式2:@ComponentScan扫描式

  • JdbcConfig类上添加注解

    @Configuration
    public class JdbcConfig {
    //@Bean:表示当前方法的返回值是一个bean对象,添加到IOC容器中
    @Bean
    public DataSource dataSource(){
    DruidDataSource ds = new DruidDataSource();
    ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
    ds.setUrl("jdbc:mysql://localhost:3306/spring_druid");
    ds.setUsername("root");
    ds.setPassword("root");
    return ds;
    }
    }

  • SpringConfig配置不变

    @Configuration // 指定这个类为配置类,替代application.xml
    @ComponentScan("com.zbbmeta")//代替<context:component-scan base-package="com.zbbmeta" />
    @PropertySource("classpath:test.properties") //如果是多个属性文件,则使用{}数组
    //@Import(JdbcConfig.class) //加载JdbcConfig配置类
    public class SpringConfig {

    }

3 注解开发为第三方Bean注入资源【重点】

问题导入

思考:配置类中如何注入简单类型数据,如何注入引用类型数据?

3.1 简单类型依赖注入

复制代码
public class JdbcConfig {
    
    @Value("com.mysql.jdbc.Driver")
    private String driver;
    @Value("jdbc:mysql://localhost:3306/spring_db")
    private String url;
    @Value("root")
    private String userName;
    @Value("root")
    private String password;
    
    //1.定义一个方法获得要管理的对象
    //2.@Bean:表示当前方法的返回值是一个bean对象,添加到IOC容器中
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

说明:如果@Value()中使用了EL表达式读取properties属性文件中的内容,那么就需要加载properties属性文件。

3.2 引用类型依赖注入

复制代码
//Spring会自动从IOC容器中根据类型找到StudentDao对象赋值给参数studentDao变量,如果没有就会报错。
    @Bean
    public DataSource dataSource(StudentDao studentDao){
        System.out.println("JdbcConfig  studentDao = " + studentDao);
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }

注意:引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象

3.3 测试类

复制代码
    @Test
    public void testDatasource() throws SQLException {

        //目标:从IOC容器中获取德鲁伊连接池对象
        //1.AnnotationConfigApplicationContext加载Spring配置类初始化Spring容器
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        //按类型获取bean
        DataSource dataSource = ac.getBean(DataSource.class);
        Connection connection = dataSource.getConnection();
        //3.打印对象
        System.out.println("连接池对象:"+dataSource);
        System.out.println("连接象地址:"+connection);
        //4.关闭容器
        ac.close();
    }

3.4 注解开发总结

相关推荐
武子康1 小时前
Java-80 深入浅出 RPC Dubbo 动态服务降级:从雪崩防护到配置中心秒级生效
java·分布式·后端·spring·微服务·rpc·dubbo
YuTaoShao3 小时前
【LeetCode 热题 100】131. 分割回文串——回溯
java·算法·leetcode·深度优先
源码_V_saaskw4 小时前
JAVA图文短视频交友+自营商城系统源码支持小程序+Android+IOS+H5
java·微信小程序·小程序·uni-app·音视频·交友
超浪的晨4 小时前
Java UDP 通信详解:从基础到实战,彻底掌握无连接网络编程
java·开发语言·后端·学习·个人开发
双力臂4045 小时前
Spring Boot 单元测试进阶:JUnit5 + Mock测试与切片测试实战及覆盖率报告生成
java·spring boot·后端·单元测试
心之语歌5 小时前
Spring AI MCP 客户端
人工智能·spring·github
Edingbrugh.南空5 小时前
Aerospike与Redis深度对比:从架构到性能的全方位解析
java·开发语言·spring
QQ_4376643145 小时前
C++11 右值引用 Lambda 表达式
java·开发语言·c++
永卿0015 小时前
设计模式-迭代器模式
java·设计模式·迭代器模式
誰能久伴不乏6 小时前
Linux如何执行系统调用及高效执行系统调用:深入浅出的解析
java·服务器·前端