@[TOC]
第三方bean管理
前面定义bean的时候都是在自己开发的类上面写个注解就完成了,但如果是第三方的类,这些类都是在jar包中,我们没有办法在类上面添加注解,这个时候该怎么办?
遇到上述问题,我们就需要有一种更加灵活的方式来定义bean,这种方式不能在原始代码上面书写注解,一样能定义bean,这就用到了一个全新的注解-- ==@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 druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUsername("root");
druidDataSource.setPassword("********");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/mybatis");
return druidDataSource;
}
}
步骤3:在方法上添加@Bean
注解
@Bean注解的作用是将方法的返回值制作为Spring管理的一个bean对象
@Configuration
public class SpringConfig {
@Bean
public DataSource dataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUsername("root");
druidDataSource.setPassword("*********");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/mybatis");
return druidDataSource;
}
}
注意:不能使用DataSource ds = new DruidDataSource()
因为DataSource接口中没有对应的setter方法来设置属性。
步骤4:从IOC容器中获取对象并打印
public class App9 {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
DataSource dataSource = ctx.getBean(DataSource.class);
System.out.println(dataSource);
}
}
结果:
如果有多个bean要被Spring管理,直接在配置类中多些几个方法,方法上添加@Bean注解即可。
引入外部配置类
如果把所有的第三方bean都配置到Spring的配置类SpringConfig
中,虽然可以,但是不利于代码阅读和分类管理,所有我们就想能不能按照类别将这些bean配置到不同的配置类中?
对于数据源的bean,我们新建一个JdbcConfig
配置类,并把数据源配置到该类下。
@Configuration
public class SpringConfig {
@Bean
public DataSource dataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUsername("root");
druidDataSource.setPassword("*********");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/mybatis");
return druidDataSource;
}
}
现在的问题是,这个配置类如何能被Spring配置类加载到,并创建DataSource对象在IOC容器中?
针对这个问题,有两个解决方案:
- 使用包扫描引入
- 使用
@Import
引入
使用包扫描引入
步骤1:在Spring的配置类上添加包扫描
@Configuration
@ComponentScan({"impl","springConfig"})
public class SpringConfig {
}
此时的项目结构:
![]()
步骤2:在JdbcConfig上添加配置注解
JdbcConfig类要放入到springConfig
包下,需要被Spring的配置类扫描到即可
@Configuration
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUsername("root");
druidDataSource.setPassword("**********");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/mybatis");
return druidDataSource;
}
}
运行程序,依然能获取到bean对象并打印控制台:
==这种方式虽然能够扫描到,但是不能很快的知晓都引入了哪些配置类,所有这种方式不推荐使用。==
使用@Import
引入
方案一实现起来有点小复杂,Spring早就想到了这一点,于是又给我们提供了第二种方案。
这种方案可以不用加@Configuration
注解,但是必须在Spring配置类上使用@Import
注解手动引入需要加载的配置类
步骤1:去除JdbcConfig类上的注解
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUsername("root");
druidDataSource.setPassword("**********");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/mybatis");
return druidDataSource;
}
}
步骤2:在Spring配置类中引入
@Configuration
//@ComponentScan({"impl","springConfig"})
@Import({JdbcConfig.class})
public class SpringConfig {
}
注意:
- 扫描注解可以移除
- @Import参数需要的是一个数组,可以引入多个配置类。
@Import注解在配置类中只能写一次,下面的方式是==不允许的==
@Configuration //@ComponentScan({"impl","springConfig"}) @Import(JdbcConfig.class) @Import(Xxx.class) public class SpringConfig { }
运行程序,依然能获取到bean对象并打印控制台:
总结
知识点1:@Bean
名称 | @Bean |
---|---|
类型 | 方法注解 |
位置 | 方法定义上方 |
作用 | 设置该方法的返回值作为spring管理的bean |
属性 | value(默认):定义bean的id |
知识点2:@Import
名称 | @Import |
---|---|
类型 | 类注解 |
位置 | 类定义上方 |
作用 | 导入配置类 |
属性 | value(默认):定义导入的配置类类名,<br/>当配置类有多个时使用数组格式一次性导入多个配置类 |
注解开发实现为第三方bean注入资源
在使用@Bean创建bean对象的时候,如果方法在创建的过程中需要其他资源该怎么办?
这些资源会有两大类,分别是简单数据类型
和引用数据类型
。
依赖简单数据类型
对于下面代码关于数据库的四要素不应该写死在代码中,应该是从properties配置文件中读取。如何来优化下面的代码?
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUsername("root");
druidDataSource.setPassword("**********");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/mybatis");
return druidDataSource;
}
}
步骤1:类中提供四个属性
@Configuration
public class JdbcConfig {
private String driver;
private String username;
private String url;
private String password;
@Bean
public DataSource dataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driver);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
druidDataSource.setUrl(url);
return druidDataSource;
}
}
步骤2:使用@Value
注解引入值
@Configuration
public class JdbcConfig {
@Value("com.mysql.jdbc.Driver")
private String driver;
@Value("root")
private String username;
@Value("jdbc:mysql://localhost:3306/mybatis")
private String url;
@Value("***********")
private String password;
@Bean
public DataSource dataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driver);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
druidDataSource.setUrl(url);
return druidDataSource;
}
}
结果:
依赖引用数据类型
步骤1:在SpringConfig中扫描BookDao
扫描的目的是让Spring能管理到BookDao,也就是说要让IOC容器中有一个bookDao对象
@Configuration
@ComponentScan({"impl","springConfig"})
@Import({JdbcConfig.class})
public class SpringConfig {
}
项目结构:
![]()
步骤2:在JdbcConfig类的方法上添加参数
@Configuration
public class JdbcConfig {
@Value("com.mysql.jdbc.Driver")
private String driver;
@Value("root")
private String username;
@Value("jdbc:mysql://localhost:3306/mybatis")
private String url;
@Value("**********")
private String password;
@Bean
public DataSource dataSource(BookDao bookDao){
System.out.println(bookDao);
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driver);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
druidDataSource.setUrl(url);
return druidDataSource;
}
}
==引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象。==
结果:
注解开发总结
XML配置和注解的开发实现两者的差异如下: