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

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

这个注解该如何使用呢?

一、环境准备

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

  • 创建一个Maven项目

  • pom.xml添加Spring的依赖

    <dependencies>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-context</artifactId>
           <version>5.2.10.RELEASE</version>
       </dependency>
    </dependencies>
  • 添加一个配置类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);
      }
    }

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

    

二、注解开发管理第三方bean

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

步骤1:导入对应的jar包

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid</artifactId>
   <version>1.1.16</version>
</dependency>

步骤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注解即可。

三、引入外部配置类

如果把所有的第三方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

名称 @Bean
类型 方法注解
位置 方法定义上方
作用 设置该方法的返回值作为spring管理的bean
属性 value(默认):定义bean的id

知识点2:@Import

名称 @Import
类型 类注解
位置 类定义上方
作用 导入配置类
属性 value(默认):定义导入的配置类类名, 当配置类有多个时使用数组格式一次性导入多个配置类

四、注解开发实现为第三方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:运行程序

五、注解开发总结

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

Java开发学习(十三)----基于注解开发定义第三方bean及注解开发总结的更多相关文章

  1. Java开发学习(十)----基于注解开发定义bean 已完成

    一.环境准备 先来准备下环境: 创建一个Maven项目 pom.xml添加Spring的依赖 <dependencies>    <dependency>        < ...

  2. Java开发学习(十一)----基于注解开发bean作用范围与生命周期管理

    一.注解开发bean作用范围与生命周期管理 前面使用注解已经完成了bean的管理,接下来将通过配置实现的内容都换成对应的注解实现,包含两部分内容:bean作用范围和bean生命周期. 1.1 环境准备 ...

  3. Java开发学习(二十七)----SpringMVC之Rest风格解析及快速开发

    一.REST简介 REST(Representational State Transfer),表现形式状态转换,它是一种软件架构风格 当我们想表示一个网络资源的时候,可以使用两种方式: 传统风格资源描 ...

  4. 【Java EE 学习 83 下】【SpringMVC】【使用注解替代已过时的API】【SpringMVC、Hibernate整合】

    一.SpringMVC中注解的使用 1.为什么要使用注解 之前曾经提到过的三种控制器在spring3.0中都已经被明确标记为过时了,spring3.0推荐使用注解的方式替代三种控制器,实际上使用注解的 ...

  5. Android开发学习笔记--给一个按钮定义事件

    学习Android的第一天,了解了各种布局,然后自己动手画出了一个按钮,然后给按钮定义了一个事件是弹出一条消息显示“我成功了!”字样,具体过程如下: 1.修改布局文件activity_main.xml ...

  6. 接单,开发,学习神器--基于SpringSecurity的后台权限管理系统

    基于SpringSecurity--码仔后台管理系统 1.技术选项 >- 核心框架 SpringBoot >- 权限框架 SpringSecurity >- 模板引擎 Thymele ...

  7. vue移动音乐app开发学习(三):轮播图组件的开发

    本系列文章是为了记录学习中的知识点,便于后期自己观看.如果有需要的同学请登录慕课网,找到Vue 2.0 高级实战-开发移动端音乐WebApp进行观看,传送门. 完成后的页面状态以及项目结构如下: 一: ...

  8. java web 学习十三(使用session防止表单重复提交)

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  9. JAVA多线程学习十三 - 同步工具CyclicBarrier与CountDownLatch

    一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序 ...

随机推荐

  1. Halo 开源项目学习(七):缓存机制

    基本介绍 我们知道,频繁操作数据库会降低服务器的系统性能,因此通常需要将频繁访问.更新的数据存入到缓存.Halo 项目也引入了缓存机制,且设置了多种实现方式,如自定义缓存.Redis.LevelDB ...

  2. Java继承实例解析

    Java继承 前言 继承是面向对象语法的三大特征之一.继承可以降低代码编写的冗余度,提高编程的效率.通过继承,子类获得了父类的成员变量和方法.一个子类如何继承父类的字段和方法,如何修改从父类继承过来的 ...

  3. 交互式 .Net 容器版

    背景介绍 在之前的文章 - 交互式 .Net 中已经介绍了什么是交互式 .Net,文中是通过 Visual Studio Code 插件的方式实现交互式 .Net 的.现在,我们将使用容器的方式实现交 ...

  4. 被迫开始学习Typescript —— class

    TS 的 class 看起来和 ES6 的 Class 有点像,基本上差别不大,除了 可以继承(实现)接口.私有成员.只读等之外. 参考:https://typescript.bootcss.com/ ...

  5. 150. Evaluate Reverse Polish Notation - LeetCode

    Question 150. Evaluate Reverse Polish Notation Solution 2 1 + 3 * 是((2+1)*3)的后缀(postfix)或逆波兰(reverse ...

  6. vue2 sass主题一键修改功能

    1.先创建一个 _theme.scss文件 作为各类主题颜色的整理 $themes: ( light: ( //字体 font_color1: #414141, font_color2: white, ...

  7. antdVue问题

    antdVue框架问题 #(1)slot/slot-scope插槽问题 一般用于表格数据渲染 eg: <span slot="user" slot-scope="t ...

  8. Acwing 1927 自动补全(知识点:hash,二分,排序)

    读完题目第一想法是trie树 ,不过好像没怎么做过trie树的题,看y总给的知识点是二分排序,所以就有了如下思路: 但是但是,看完其他题解之后才坚定了我的想法,原来真的是这样排序,暴力啊! 具体步骤 ...

  9. 基于开源流程引擎开发BPM或OA有哪些难点

    前言     如何基于开源流程引擎开发OA系统?开源流程引擎哪个好?把它整合到自己的产品里难不难,有没有啥风险?这是大家经常遇到的问题.笔者从2006年开始参与流程引擎开发,经历了三代流程引擎研发,支 ...

  10. SQL Server 2008~2019版本序列号/密钥/激活码 汇总

    SQL Server 2019 Enterprise:HMWJ3-KY3J2-NMVD7-KG4JR-X2G8G Strandard:PMBDC-FXVM3-T777P-N4FY8-PKFF4 SQL ...