1、IOC/DI注解开发
Spring的IOC/DI对应的配置开发使用起来相对来说还是比较复杂的,复杂的地方在配置文件。
我们知道Spring可以简化代码的开发,所以Spring到底是如何简化代码开发的呢?
要想真正简化开发,就需要用到Spring的注解开发,Spring对注解支持的版本历程:
- 2.0版开始支持注解
- 2.5版注解功能趋于完善
- 3.0版支持纯注解开发
关于注解开发,分两块内容 注解开发定义bean
和纯注解开发
。
注解开发定义bean用的是2.5版提供的注解,纯注解开发用的是3.0版提供的注解。
1.1 环境准备
先来准备下案例环境:
- 创建一个Maven项目
- pom.xml添加Spring的依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>
- resources下添加applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bookDao" class="com.spring.dao.impl.BookDaoImpl"/>
</beans>
- 添加BookDao、BookDaoImpl、BookService、BookServiceImpl类
package com.spring.dao;
public interface BookDao {
public void save();
}
package com.spring.dao.impl;
import com.spring.dao.BookDao;
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
}
package com.spring.service;
public interface BookService {
public void save();
}
package com.spring.service.impl;
import com.spring.service.BookService;
public class BookServiceImpl implements BookService {
public void save() {
System.out.println("book service save ...");
}
}
- 创建运行类App
package com.spring;
import com.spring.dao.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class app {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
}
}
最终创建好的项目结构如下:
成品、素材下载:Spring: Spring的笔记、案例
2、注解开发定义bean
在上述准备好的环境中,我们来实现Spring通过注解实现bean的定义开发!
步骤1:删除原XML配置
将配置文件中的<bean>
标签删除掉
<bean id="bookDao" class="com.spring.dao.impl.BookDaoImpl"/>
步骤2:Dao上添加注解
在BookDaoImpl类上添加@Component
注解
package com.spring.dao.impl;
import com.spring.dao.BookDao;
import org.springframework.stereotype.Component;
@Component("bookDao")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
}
注意:@Component注解不可以添加在接口上,因为接口是无法创建对象的。
XML与注解配置的对应关系:
步骤3:配置Spring的注解包扫描
为了让Spring框架能够扫描到写在类上的注解,需要在配置文件applicationContext.xml上进行包扫描
<?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 https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.spring" />
</beans>
说明:
component-scan
- component:组件,Spring将管理的bean视作自己的一个组件
- scan:扫描
base-package指定Spring框架扫描的包路径,它会扫描指定包及其子包中的所有类上的注解。
- 包路径越多[如:com.spring.dao.impl],扫描的范围越小速度越快
- 包路径越少[如:com.spring],扫描的范围越大速度越慢
- 一般扫描到项目的组织名称即Maven的groupId下[如:com.spring]即可。
步骤4:运行程序
运行app
类查看打印结果
步骤5:Service上添加注解
用第二种方法:使用类型获取bean
package com.spring.service.impl;
import com.spring.dao.BookDao;
import com.spring.service.BookService;
import org.springframework.stereotype.Component;
@Component
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
步骤6:运行程序
在App类中,从IOC容器中获取BookServiceImpl对应的bean对象,打印
package com.spring;
import com.spring.dao.BookDao;
import com.spring.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class app {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
System.out.println(bookDao);
BookService bookService = ctx.getBean(BookService.class);
System.out.println(bookService);
}
}
打印观察结果,两个bean对象都已经打印到控制台
说明:
- BookServiceImpl类没有起名称,所以在App中是按照类型来获取bean对象
- @Component注解如果不起名称,会有一个默认值就是
当前类名首字母小写
,所以也可以按照名称获取,如
BookService bookService = (BookService)ctx.getBean("bookServiceImpl");
System.out.println(bookService);
对于@Component注解,还衍生出了其他三个注解@Controller
、@Service
、@Repository
这三个注解和@Component注解的作用是一样的,方便我们后期在编写类的时候能很好的区分出这个类是属于表现层
、业务层
还是数据层
的类。
知识点总结
知识点1:@Component
名称 | @Component/@Controller/@Service/@Repository |
类型 | 类注解 |
位置 | 类定义上方 |
作用 | 设置该类为spring管理的bean |
属性 | value(默认):定义bean的id |
3、纯注解开发模式
上面已经可以使用注解来配置bean,但是依然有用到配置文件,在配置文件中对包进行了扫描,Spring在3.0版已经支持纯注解开发
- Spring3.0开启了纯注解开发模式,使用Java类替代配置文件,开启了Spring快速开发赛道
环境准备
在spring_01项目基础上,创建spring_02项目
成品、素材下载:Spring: Spring的笔记、案例
思路分析
实现思路为:
- 将配置文件applicationContext.xml删除掉,使用类来替换。
实现步骤
步骤1:创建配置类
创建一个配置类SpringConfig
package com.spring.config;
public class SpringConfig {
}
步骤2:标识该类为配置类
package com.spring.config;
import org.springframework.beans.factory.annotation.Configurable;
@Configurable
public class SpringConfig {
}
步骤3:用注解替换包扫描配置
在配置类上添加包扫描注解@ComponentScan
替换<context:component-scan base-package=""/>
将applicationContext.xml文件中的 <context:component-scan base-package=""/> 删除
package com.spring.config;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.ComponentScan;
@Configurable
@ComponentScan("com.spring")
public class SpringConfig {
}
步骤4:创建运行类并执行
创建一个新的运行类AppForAnnotation
import com.spring.config.SpringConfig;
import com.spring.dao.BookDao;
import com.spring.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class AppForAnnotation {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
System.out.println(bookDao);
BookService bookService = ctx.getBean(BookService.class);
System.out.println(bookService);
}
}
运行AppForAnnotation,可以看到两个对象依然被获取成功
至此,纯注解开发的方式就已经完成了,主要内容包括:
- Java类替换Spring核心配置文件
- @Configuration注解用于设定当前类为配置类
- @ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式
@ComponentScan({com.spring.service","com.spring.dao"})
- 读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象
//加载配置文件初始化容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//加载配置类初始化容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
知识点总结
知识点1:@Configuration
名称 | |
类型 | 类注解 |
位置 | 类定义上方 |
作用 | 设置该类为spring配置类 |
属性 | value(默认):定义bean的id |
知识点2:@ComponentScan
名称 | |
类型 | 类注解 |
位置 | 类定义上方 |
作用 | 设置spring配置类扫描路径,用于加载使用注解格式定义的bean |
属性 | value(默认):扫描路径,此路径可以逐层向下扫描 |
小结:
重点掌握的是使用注解完成Spring的bean管理,需要掌握的内容为:
- 记住@Component、@Controller、@Service、@Repository这四个注解
- applicationContext.xml中
<context:component-san/>
的作用是指定扫描包路径,注解为@ComponentScan
- @Configuration标识该类为配置类,使用类替换applicationContext.xml文件
- ClassPathXmlApplicationContext是加载XML配置文件
- AnnotationConfigApplicationContext是加载配置类
成品、素材下载:Spring: Spring的笔记、案例
4、注解开发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
package com.spring.config;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.ComponentScan;
@Configurable
@ComponentScan("com.spring")
public class SpringConfig {
}
- 添加BookDao、BookDaoImpl类
package com.spring.dao;
public interface BookDao {
public void save();
}
package com.spring.dao.impl;
import com.spring.dao.BookDao;
import org.springframework.stereotype.Repository;
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
}
Bean的作用范围
结构项目与运行结果:
在控制台打印两个一摸一样的地址,说明默认情况下bean是单例
要想将BookDaoImpl变成非单例,只需要在其类上添加@scope
注解
知识点1:@Scope
名称 | |
类型 | 类注解 |
位置 | 类定义上方 |
作用 | 设置该类创建对象的作用范围 |
属性 | value(默认):定义bean作用范围, |
Bean的生命周期
在BookDaoImpl中添加两个方法,init
和destroy
,方法名可以任意
package com.spring.dao.impl;
import com.spring.dao.BookDao;
import org.springframework.stereotype.Repository;
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
public void init() {
System.out.println("init ...");
}
public void destroy() {
System.out.println("destroy ...");
}
}
@PostConstruct 标识初始化方法,@PreDestroy标识销毁方法,只需要在对应的方法上添加注解
package com.spring.dao.impl;
import com.spring.dao.BookDao;
import org.springframework.stereotype.Repository;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
@PostConstruct // 构造方法之后执行,替换 init-method
public void init() {
System.out.println("init ...");
}
@PreDestroy // 在销毁方法之前执行,替换 destroy-method
public void destroy() {
System.out.println("destroy ...");
}
}
运行 app 类
注意:@PostConstruct和@PreDestroy注解如果找不到,需要导入下面的jar包
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
找不到的原因是,从JDK9以后jdk中的javax.annotation包被移除了,这两个注解刚好就在这个包中。
知识点1:@PostConstruct
名称 | |
类型 | 方法注解 |
位置 | 方法上 |
作用 | 设置该方法为初始化方法 |
属性 | 无 |
知识点2:@PreDestroy
名称 | |
类型 | 方法注解 |
位置 | 方法上 |
作用 | 设置该方法为销毁方法 |
属性 | 无 |
总结
5、注解开发依赖注入
Spring为了使用注解简化开发,并没有提供构造函数注入
、setter注入
对应的注解,只提供了自动装配的注解实现。
环境准备
- 创建一个Maven项目
- pom.xml添加Spring的依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>
- 添加一个配置类
SpringConfig
package com.spring.config;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.ComponentScan;
@Configurable
@ComponentScan("com.spring")
public class SpringConfig {
}
- 添加BookDao、BookDaoImpl、BookService、BookServiceImpl类
public interface BookDao {
public void save();
}
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
}
public interface BookService {
public void save();
}
@Service
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
- 创建运行类App 以及 项目结构
运行后会发现 报出空指针异常
出现问题的原因是,在BookServiceImpl类中添加了BookDao的属性,并提供了setter方法,但是目前是没有提供配置注入BookDao的,所以bookDao对象为Null,调用其save方法就会报控指针异常
。
注解实现按照类型注入
在BookServiceImpl类的bookDao属性上添加@Autowired
注解,并且将set方法注释或者删除
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
注意:
- @Autowired可以写在属性上,也可也写在setter方法上,最简单的处理方式是
写在属性上并将setter方法删除掉
- 为什么setter方法可以删除呢?
-
- 自动装配基于反射设计创建对象并通过暴力反射为私有属性进行设值
-
- 普通反射只能获取public修饰的内容
-
- 暴力反射除了获取public修饰的内容还可以获取private修改的内容
-
- 所以此处无需提供setter方法
@Autowired是按照类型注入,那么对应BookDao接口如果有多个实现类,比如添加BookDaoImpl2
@Repository
public class BookDaoImpl2 implements BookDao {
public void save() {
System.out.println("book dao save ...2");
}
}
这个时候再次运行App,就会报错
此时,按照类型注入就无法区分到底注入哪个对象,解决方案:按照名称注入
- 先给两个Dao类分别起个名称
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
}
@Repository("bookDao2")
public class BookDaoImpl2 implements BookDao {
public void save() {
System.out.println("book dao save ...2" );
}
}
此时就可以注入成功,但是得思考个问题:
-
- @Autowired是按照类型注入的,给BookDao的两个实现起了名称,它还是有两个bean对象,为什么不报错?
-
- @Autowired默认按照类型自动装配,如果IOC容器中同类的Bean找到多个,就按照变量名和Bean的名称匹配。因为变量名叫
bookDao
而容器中也有一个booDao
,所以可以成功注入。
- @Autowired默认按照类型自动装配,如果IOC容器中同类的Bean找到多个,就按照变量名和Bean的名称匹配。因为变量名叫
-
- 分析下面这种情况是否能完成注入呢?
-
- 不行,因为按照类型会找到多个bean对象,此时会按照
bookDao
名称去找,因为IOC容器只有名称叫bookDao1
和bookDao2
,所以找不到,会报NoUniqueBeanDefinitionException
- 不行,因为按照类型会找到多个bean对象,此时会按照
注解实现按照名称注入
当根据类型在容器中找到多个bean,注入参数的属性名又和容器中bean的名称不一致,这个时候该如何解决,就需要使用到@Qualifier
来指定注入哪个名称的bean对象。
@Service
public class BookServiceImpl implements BookService {
@Autowired
@Qualifier("bookDao1")
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
@Qualifier注解后的值就是需要注入的bean的名称。
注意:@Qualifier不能独立使用,必须和@Autowired一起使用
注解简单数据类型注入
引用类型看完,简单类型注入就比较容易懂了。简单类型注入的是基本数据类型或者字符串类型,下面在BookDaoImpl类中添加一个name属性,用其进行简单类型注入
@Repository("bookDao1")
public class BookDaoImpl implements BookDao {
private String name;
public void save() {
System.out.println("book dao save ..." + name);
}
}
数据类型换了,对应的注解也要跟着换,这次使用@Value
注解,将值写入注解的参数中就行了
注意数据格式要匹配,如将"abc"注入给int值,这样程序就会报错。
介绍完后,会有一种感觉就是这个注解好像没什么用,跟直接赋值是一个效果,还没有直接赋值简单,所以这个注解存在的意义是什么?
注解读取properties配置文件
@Value
一般会被用在从properties配置文件中读取内容进行使用,具体如何实现?
步骤1:resource下创建 jdbc.properties 文件
name=spring123
步骤2:使用注解加载properties配置文件
在配置类上添加@PropertySource
注解
@Configurable
@ComponentScan("com.spring")
@PropertySource("jdbc.properties")
public class SpringConfig {
}
步骤3:使用@Value读取配置文件中的内容
注意:
- 如果读取的properties配置文件有多个,可以使用
@PropertySource
的属性来指定多个
@PropertySource({"jdbc.properties","xxx.properties"})
@PropertySource
注解属性中不支持使用通配符*
,运行会报错
@PropertySource({"*.properties"})
@PropertySource
注解属性中可以把classpath:
加上,代表从当前项目的根路径找文件
@PropertySource({"classpath:jdbc.properties"})
知识点总结
知识点1:@Autowired
名称 | |
类型 | 属性注解 或 方法注解(了解) 或 方法形参注解(了解) |
位置 | 属性定义上方 或 标准set方法上方 或 类set方法上方 或 方法形参前面 |
作用 | 为引用类型属性设置值 |
属性 | required:true/false,定义该属性是否允许为null |
知识点2:@Qualifier
名称 | |
类型 | 属性注解 或 方法注解(了解) |
位置 | 属性定义上方 或 标准set方法上方 或 类set方法上方 |
作用 | 为引用类型属性指定注入的beanId |
属性 | value(默认):设置注入的beanId |
知识点3:@Value
名称 | |
类型 | 属性注解 或 方法注解(了解) |
位置 | 属性定义上方 或 标准set方法上方 或 类set方法上方 |
作用 | 为 基本数据类型 或 字符串类型 属性设置值 |
属性 | value(默认):要注入的属性值 |
知识点4:@PropertySource
名称 | |
类型 | 类注解 |
位置 | 类定义上方 |
作用 | 加载properties文件中的属性值 |
属性 | value(默认):设置加载的properties文件对应的文件名或文件名组成的数组 |
6、IOC/DI注解开发管理第三方bean
前面定义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 类 ,项目结构预览
在上述环境中完成对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(){
@Bean
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方法来设置属性。
步骤3:从IOC容器中获取对象并打印
至此使用@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容器中?
针对这个问题,有两个解决方案:
使用包扫描引入
步骤1:在Spring的配置类上添加包扫描
@Configuration
@ComponentScan("com.spring.config")
public class SpringConfig {
}
步骤2:在JdbcConfig上添加配置注解
JdbcConfig类要放入到com.spring.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对象并打印控制台。
这种方式虽然能够扫描到,但是不能很快的知晓都引入了哪些配置类,所有这种方式不推荐使用。
使用@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.spring.config")
@Import({JdbcConfig.class})
public class SpringConfig {
}
注意:
- 扫描注解可以移除
- @Import参数需要的是一个数组,可以引入多个配置类。
- @Import注解在配置类中只能写一次,不能存在多个@Import注解
步骤3:运行程序
依然能获取到bean对象并打印控制台
知识点总结
知识点1:@Bean
名称 | |
类型 | 方法注解 |
位置 | 方法定义上方 |
作用 | 设置该方法的返回值作为spring管理的bean |
属性 | value(默认):定义bean的id |
知识点2:@Import
名称 | |
类型 | 类注解 |
位置 | 类定义上方 |
作用 | 导入配置类 |
属性 | value(默认):定义导入的配置类类名, |
注解开发实现为第三方bean注入资源
在使用@Bean创建bean对象的时候,如果方法在创建的过程中需要其他资源该怎么办?
这些资源会有两大类,分别是简单数据类型
和引用数据类型
。
对于下面代码关于数据库的四要素不应该写死在代码中,应该是从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;
}
}
简单数据类型
步骤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("root")
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;
}
}
引用数据类型
步骤1:在SpringConfig中扫描BookDao
扫描的目的是让Spring能管理到BookDao,也就是说要让IOC容器中有一个bookDao对象
@Configuration
@ComponentScan("com.spring.config")
@Import({JdbcConfig.class})
public class SpringConfig {
}
步骤2:在JdbcConfig类的方法上添加参数,然后执行查看效果
引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象。
注解开发总结
XML配置和注解的开发实现,至于两者之间的差异,咱们放在一块去对比回顾下:
成品、素材下载:Spring: Spring的笔记、案例