【Spring教程11】Spring框架实战:IOCDI注解开发管理第三方bean的全面深入详解
作者:mmseoamin日期:2023-12-11

目录

  • 1 环境准备
  • 2 注解开发管理第三方bean
  • 3 引入外部配置类
    • 3.1 使用包扫描引入
    • 3.2 使用@Import引入
    • 4 注解开发实现为第三方bean注入资源
      • 4.1 简单数据类型
        • 4.1.1 需求分析
        • 4.1.2 注入简单数据类型步骤
        • 4.2 引用数据类型
          • 4.2.1 需求分析
          • 4.2.2 注入引用数据类型步骤
          • 5 注解开发总结

            欢迎大家回到《 Java教程之Spring30天快速入门》,本教程所有示例均基于Maven实现,如果您对Maven还很陌生,请移步本人的博文《 如何在windows11下安装Maven并配置以及 IDEA配置Maven环境》,本文的上一篇为《 纯注解开发模式下的依赖注入和读取properties配置文件》

            在这里插入图片描述

            前面定义bean的时候都是在自己开发的类上面写个注解就完成了,但如果是第三方的类,这些类都是在jar包中,我们没有办法在类上面添加注解,这个时候该怎么办?

            遇到上述问题,我们就需要有一种更加灵活的方式来定义bean,这种方式不能在原始代码上面书写注解,一样能定义bean,这就用到了一个全新的注解@Bean。

            这个注解该如何使用呢?

            咱们把之前使用配置方式管理的数据源使用注解再来一遍,通过这个案例来学习下@Bean的使用。

            1 环境准备

            学习@Bean注解之前先来准备环境:

            • 创建一个Maven项目
            • pom.xml添加Spring的依赖
              
              	
              		org.springframework
              		spring-context
              		5.2.10.RELEASE
              	
              
              
              • 添加一个配置类SpringConfig
                @Configuration
                public class SpringConfig {
                }
                
                • 添加BookDao、BookDaoImpl类
                  public interface BookDao {
                  	public void save();
                  }
                  @Repository
                  public class BookDaoImpl implements BookDao {
                  	public void save() {
                  		System.out.println("book dao save ..." );
                  	}
                  }
                  
                  • 创建运行类App
                    public class App {
                    	public static void main(String[] args) {
                    		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
                    	}
                    }
                    

                    最终创建好的项目结构如下:

                    在这里插入图片描述

                    2 注解开发管理第三方bean

                    在上述环境中完成对Druid数据源的管理,具体的实现步骤为:

                    步骤1:导入对应的jar包

                    
                    	com.alibaba
                    	druid
                    	1.1.16
                    
                    

                    步骤2:在配置类中添加一个方法

                    注意该方法的返回值就是要创建的Bean对象类型

                    @Configuration
                    public class SpringConfig {
                    	public DataSource dataSource(){
                    		DruidDataSource ds = new DruidDataSource();
                    		ds.setDriverClassName("com.mysql.jdbc.Driver");
                    		ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
                    		ds.setUsername("root");
                    		ds.setPassword("root");
                    		return ds;
                    	}
                    }
                    

                    步骤3:在方法上添加@Bean注解

                    @Bean注解的作用是将方法的返回值制作为Spring管理的一个bean对象

                    @Configuration
                    public class SpringConfig {
                    	@Bean
                    	public DataSource dataSource(){
                    		DruidDataSource ds = new DruidDataSource();
                    		ds.setDriverClassName("com.mysql.jdbc.Driver");
                    		ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
                    		ds.setUsername("root");
                    		ds.setPassword("root");
                    		return ds;
                    	}
                    }
                    

                    注意:不能使用DataSource ds = new DruidDataSource()

                    因为DataSource接口中没有对应的setter方法来设置属性。

                    步骤4:从IOC容器中获取对象并打印

                    public class App {
                    	public static void main(String[] args) {
                    		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
                    		DataSource dataSource = ctx.getBean(DataSource.class);
                    		System.out.println(dataSource);
                    	}
                    }
                    

                    至此使用@Bean来管理第三方bean的案例就已经完成。

                    如果有多个bean要被Spring管理,直接在配置类中多些几个方法,方法上添加@Bean注解即可。

                    3 引入外部配置类

                    如果把所有的第三方bean都配置到Spring的配置类SpringConfig中,虽然可以,但是不利于代码阅读和分类管理,所有我们就想能不能按照类别将这些bean配置到不同的配置类中?

                    对于数据源的bean,我们新建一个JdbcConfig配置类,并把数据源配置到该类下。

                    public class JdbcConfig {
                    	@Bean
                    	public DataSource dataSource(){
                    		DruidDataSource ds = new DruidDataSource();
                    		ds.setDriverClassName("com.mysql.jdbc.Driver");
                    		ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
                    		ds.setUsername("root");
                    		ds.setPassword("root");
                    		return ds;
                    	}
                    }
                    

                    现在的问题是,这个配置类如何能被Spring配置类加载到,并创建DataSource对象在IOC容器中?

                    针对这个问题,有两个解决方案:

                    3.1 使用包扫描引入

                    步骤1:在Spring的配置类上添加包扫描

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

                    步骤2:在JdbcConfig上添加配置注解

                    JdbcConfig类要放入到com.itheima.config包下,需要被Spring的配置类扫描到即可

                    @Configuration
                    public class JdbcConfig {
                    	@Bean
                    	public DataSource dataSource(){
                    		DruidDataSource ds = new DruidDataSource();
                    		ds.setDriverClassName("com.mysql.jdbc.Driver");
                    		ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
                    		ds.setUsername("root");
                    		ds.setPassword("root");
                    		return ds;
                    	}
                    }
                    

                    步骤3:运行程序

                    依然能获取到bean对象并打印控制台。

                    这种方式虽然能够扫描到,但是不能很快的知晓都引入了哪些配置类,所有这种方式不推荐使用。

                    3.2 使用@Import引入

                    方案一实现起来有点小复杂,Spring早就想到了这一点,于是又给我们提供了第二种方案。

                    这种方案可以不用加@Configuration注解,但是必须在Spring配置类上使用@Import注解手动引入需要加载的配置类

                    步骤1:去除JdbcConfig类上的注解

                    public class JdbcConfig {
                    	@Bean
                    	public DataSource dataSource(){
                    		DruidDataSource ds = new DruidDataSource();
                    		ds.setDriverClassName("com.mysql.jdbc.Driver");
                    		ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
                    		ds.setUsername("root");
                    		ds.setPassword("root");
                    		return ds;
                    	}
                    }
                    

                    步骤2:在Spring配置类中引入

                    @Configuration
                    //@ComponentScan("com.itheima.config")
                    @Import({JdbcConfig.class})
                    public class SpringConfig {
                    }
                    

                    注意:

                    • 扫描注解可以移除
                    • @Import参数需要的是一个数组,可以引入多个配置类。
                    • @Import注解在配置类中只能写一次,下面的方式是不允许的
                      @Configuration
                      //@ComponentScan("com.itheima.config")
                      @Import(JdbcConfig.class)
                      @Import(Xxx.class)
                      public class SpringConfig {
                      }
                      

                      步骤3:运行程序

                      依然能获取到bean对象并打印控制台

                      知识点1:@Bean

                      在这里插入图片描述

                      知识点2:@Import

                      在这里插入图片描述

                      4 注解开发实现为第三方bean注入资源

                      在使用@Bean创建bean对象的时候,如果方法在创建的过程中需要其他资源该怎么办?

                      这些资源会有两大类,分别是简单数据类型 和引用数据类型。

                      4.1 简单数据类型

                      4.1.1 需求分析

                      对于下面代码关于数据库的四要素不应该写死在代码中,应该是从properties配置文件中读取。如何来优化下面的代码?

                      public class JdbcConfig {
                      	@Bean
                      	public DataSource dataSource(){
                      		DruidDataSource ds = new DruidDataSource();
                      		ds.setDriverClassName("com.mysql.jdbc.Driver");
                      		ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
                      		ds.setUsername("root");
                      		ds.setPassword("root");
                      		return ds;
                      	}
                      }
                      

                      4.1.2 注入简单数据类型步骤

                      步骤1:类中提供四个属性

                      public class JdbcConfig {
                      	private String driver;
                      	private String url;
                      	private String userName;
                      	private String password;
                      	@Bean
                      	public DataSource dataSource(){
                      		DruidDataSource ds = new DruidDataSource();
                      		ds.setDriverClassName("com.mysql.jdbc.Driver");
                      		ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
                      		ds.setUsername("root");
                      		ds.setPassword("root");
                      		return ds;
                      	}
                      }
                      

                      步骤2:使用@Value注解引入值

                      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("password")
                      	private String password;
                      	@Bean
                      	public DataSource dataSource(){
                      		DruidDataSource ds = new DruidDataSource();
                      		ds.setDriverClassName(driver);
                      		ds.setUrl(url);
                      		ds.setUsername(userName);
                      		ds.setPassword(password);
                      		return ds;
                      	}
                      }
                      

                      扩展

                      现在的数据库连接四要素还是写在代码中,需要做的是将这些内容提

                      取到jdbc.properties配置文件,大家思考下该如何实现?

                      1.resources目录下添加jdbc.properties

                      2.配置文件中提供四个键值对分别是数据库的四要素

                      3.使用@PropertySource加载jdbc.properties配置文件

                      4.修改@Value注解属性的值,将其修改为${key},key就是键值对中的键的值

                      具体的实现就交由大家自行实现下。

                      4.2 引用数据类型

                      4.2.1 需求分析

                      假设在构建DataSource对象的时候,需要用到BookDao对象,该如何把BookDao对象注入进方法内让其使用呢?

                      public class JdbcConfig {
                      	@Bean
                      	public DataSource dataSource(){
                      		DruidDataSource ds = new DruidDataSource();
                      		ds.setDriverClassName("com.mysql.jdbc.Driver");
                      		ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
                      		ds.setUsername("root");
                      		ds.setPassword("root");
                      		return ds;
                      	}
                      }
                      

                      4.2.2 注入引用数据类型步骤

                      步骤1:在SpringConfig中扫描BookDao

                      扫描的目的是让Spring能管理到BookDao,也就是说要让IOC容器中有一个bookDao对象

                      @Configuration
                      @ComponentScan("com.itheima.dao")
                      @Import({JdbcConfig.class})
                      public class SpringConfig {
                      }
                      

                      步骤2:在JdbcConfig类的方法上添加参数

                      @Bean
                      public DataSource dataSource(BookDao bookDao){
                      	System.out.println(bookDao);
                      	DruidDataSource ds = new DruidDataSource();
                      	ds.setDriverClassName(driver);
                      	ds.setUrl(url);
                      	ds.setUsername(userName);
                      	ds.setPassword(password);
                      	return ds;
                      }
                      

                      引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象。 **步骤3:运行程序**

                      在这里插入图片描述

                      5 注解开发总结

                      前面我们已经完成了XML配置和注解的开发实现,至于两者之间的差异,咱们放在一块去对比回顾下:

                      在这里插入图片描述