当前位置: 首页 > news >正文

【Spring篇】IOC/DI注解开发

🍓系列专栏:Spring系列专栏

🍉个人主页:个人主页

目录

一、IOC/DI注解开发

1.注解开发定义bean 

2.纯注解开发模式

1.思路分析

2.实现步骤

3.注解开发bean作用范围与生命周期管理

1.环境准备

2.Bean的作用范围

3.Bean的生命周期

4.注解开发依赖注入

1.环境准备

2.注解实现按照类型注入

3.注解实现按照名称注入

4.简单数据类型注入

5.注解读取properties配置文件

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

1.环境准备

2.注解开发管理第三方bean

3.引入外部配置类

1.使用包扫描引入

2.使用@Import引入

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

1.简单数据类型

2.引用数据类型 

三、注解开发总结


一、IOC/DI注解开发

Spring IOC/DI 对应的配置开发就已经讲解完成,但是使用起来相对来说还是比较复杂的,复杂的
地方在 配置文件
前面咱们聊 Spring 的时候说过, Spring 可以简化代码的开发,到现在并没有体会到。
所以 Spring 到底是如何简化代码开发的呢 ?
要想真正简化开发,就需要用到 Spring 的注解开发, Spring 对注解支持的版本历程 :
  • 2.0版开始支持注解
  • 2.5版注解功能趋于完善3.0版支持纯注解开发
关于注解开发,我们会讲解两块内容 注解开发定义 bean 纯注解开发
注解开发定义 bean 用的是 2.5 版提供的注解,纯注解开发用的是 3.0 版提供的注解。

环境准备

在学习注解开发之前,先来准备下案例环境:

  • 创建一个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.itheima.dao.impl.BookDaoImpl"/>
</beans>
  • 添加 BookDao BookDaoImpl BookService BookServiceImpl
public interface BookDao {
public void save();
}
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
}
public interface BookService {
public void save();
}
public class BookServiceImpl implements BookService {
public void save() {
System.out.println("book service save ...");
}
}
  • 创建运行类App
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new
ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
}
}
最终创建好的项目结构如下 :

1.注解开发定义bean 

步骤 1: 删除原 XML 配置
将配置文件中的 <bean> 标签删除掉
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
步骤 2:Dao 上添加注解
BookDaoImpl 类上添加 @Component 注解
@Component("bookDao")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
}
注意 :@Component 注解不可以添加在接口上,因为接口是无法创建对象的。
XML 与注解配置的对应关系 :

步骤3:配置Spring的注解包扫描

为了让Spring框架能够扫描到写在类上的注解,需要在配置文件上进行包扫描

<?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">
<context:component-scan base-package="com.itheima"/>
</beans>

说明 :
component-scan
  • component:组件,Spring将管理的bean视作自己的一个组件
  • scan:扫描
base-package 指定 Spring 框架扫描的包路径,它会扫描指定包及其子包中的所有类上的注解。
  • 包路径越多[:com.itheima.dao.impl],扫描的范围越小速度越快
  • 包路径越少[:com.itheima],扫描的范围越大速度越慢
  • 一般扫描到项目的组织名称即MavengroupId[:com.itheima]即可。
步骤 4 :运行程序
运行 App 类查看打印结果

步骤 5:Service 上添加注解
BookServiceImpl 类上也添加 @Component 交给 Spring 框架管理
@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 对象,打印
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);
//按类型获取bean
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(默认):定义beanid

2.纯注解开发模式

上面已经可以使用注解来配置bean, 但是依然有用到配置文件,在配置文件中对包进行了扫描,
Spring 3.0 版已经支持纯注解开发
  • Spring3.0开启了纯注解开发模式,使用Java类替代配置文件,开启了Spring快速开发赛道具体如何实现?

1.思路分析

实现思路为 :
将配置文件 applicationContext.xml 删除掉,使用类来替换。

2.实现步骤

步骤 1: 创建配置类
创建一个配置类 SpringConfig
public class SpringConfig {
}
步骤 2: 标识该类为配置类
在配置类上添加 @Configuration 注解,将其标识为一个配置类 , 替换 applicationContext.xml
@Configuration
public class SpringConfig {
}
步骤 3: 用注解替换包扫描配置
在配置类上添加包扫描注解 @ComponentScan 替换 <context:component - scan base - package=""/>
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}
步骤 4: 创建运行类并执行
创建一个新的运行类 AppForAnnotation
public class AppForAnnotation {public static void main(String[] args) {//AnnotationConfigApplicationContext加载Spring配置类初始化Spring容器ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao = (BookDao) ctx.getBean("bookDao");System.out.println(bookDao);//按类型获取beanBookService bookService = ctx.getBean(BookService.class);System.out.println(bookService);}
}
运行 AppForAnnotation, 可以看到两个对象依然被获取成功

至此,纯注解开发的方式就已经完成了,主要内容包括 :
  • Java类替换Spring核心配置文件

  • @Configuration注解用于设定当前类为配置类
  • @ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式
@ComponentScan({com.itheima.service","com.itheima.dao"})
  •  读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象
//加载配置文件初始化容器
ApplicationContext ctx = new
ClassPathXmlApplicationContext("applicationContext.xml");
//加载配置类初始化容器
ApplicationContext ctx = new
AnnotationConfigApplicationContext(SpringConfig.class);
知识点 1 @Configuration
名称@Configuration
类型类注解
位置类定义上方
作用设置该类为spring配置类
属性value(默认):定义beanid

知识点 2 @ComponentScan
名称@ComponentScan
类型类注解
位置类定义上方
作用设置spring配置类扫描路径,用于加载使用注解格式定义的bean
属性value(默认):扫描路径,此路径可以逐层向下扫描

小结 :
这一节重点掌握的是使用注解完成 Spring bean 管理,需要掌握的内容为 :
  • 记住@Component@Controller@Service@Repository这四个注解
  • applicationContext.xml<context:component-san/>的作用是指定扫描包路径,注解为 @ComponentScan
  • @Configuration标识该类为配置类,使用类替换applicationContext.xml文件
  • ClassPathXmlApplicationContext是加载XML配置文件
  • AnnotationConfigApplicationContext是加载配置类

3.注解开发bean作用范围与生命周期管理

使用注解已经完成了 bean 的管理,接下来按照前面所学习的内容,将通过配置实现的内容都换成对应的注解实现,包含两部分内容: bean 作用范围 bean 生命周期

1.环境准备

老规矩,学习之前先来准备环境 :
  • 创建一个Maven项目
  • pom.xml添加Spring的依赖【之前的】
  • 添加一个配置类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);
BookDao bookDao1 = ctx.getBean(BookDao.class);
BookDao bookDao2 = ctx.getBean(BookDao.class);
System.out.println(bookDao1);
System.out.println(bookDao2);
}
}
最终创建好的项目结构如下 :

2.Bean的作用范围

(1)先运行App,在控制台打印两个一摸一样的地址,说明默认情况下bean是单例

(2)要想将BookDaoImpl变成非单例,只需要在其类上添加@scope注解

@Repository
//@Scope设置bean的作用范围
@Scope("prototype")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}

 

知识点@Scope  

名称
@Scope
类型类注解
位置类定义上方
作用
设置该类创建对象的作用范围
可用于设置创建出的 bean 是否为单例对象
属性
value (默认):定义 bean 作用范围,
默认值 singleton (单例),可选值 prototype (非单例)

3.Bean的生命周期

(1) BookDaoImpl 中添加两个方法, init destroy , 方法名可以任意.
在对应的方法上添加 @PostConstruct 和  @PreDestroy 注解
@Repository
//@Scope设置bean的作用范围public class BookDaoImpl implements BookDao {public void save() {System.out.println("book dao save ...");}
//    @PostConstruct设置bean的初始化方法@PostConstructpublic void init() {System.out.println("init ...");}//@PreDestroy设置bean的销毁方法@PreDestroypublic void destroy() {System.out.println("destroy ...");}}
(2) 要想看到两个方法执行,需要注意的是 destroy 只有在容器关闭的时候,才会执行,所以需要修
App 的类
public class App {public static void main(String[] args) {AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao1 = ctx.getBean(BookDao.class);BookDao bookDao2 = ctx.getBean(BookDao.class);System.out.println(bookDao1);System.out.println(bookDao2);ctx.close();}
}

运行App,类查看打印结果,证明initdestroy方法都被执行了。

 注意:@PostConstruct@PreDestroy注解如果找不到,需要导入下面的jar

<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
找不到的原因是,从 JDK9 以后 jdk 中的 javax.annotation 包被移除了,这两个注解刚好就在这个包
中。

 小结

4.注解开发依赖注入

Spring为了使用注解简化开发,并没有提供构造函数注入setter注入对应的注解,只提供了自动装配的注解实现。

1.环境准备

在学习之前,把案例环境介绍下 :
  • 创建一个Maven项目
  • pom.xml添加Spring的依赖
  • 添加一个配置类SpringConfig
  • 添加BookDaoBookDaoImplBookServiceBookServiceImpl
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();}@Servicepublic 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
public class App {public static void main(String[] args) {AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);BookService bookService = ctx.getBean(BookService.class);bookService.save();}
}
最终创建好的项目结构如下 :

 环境准备好后,运行后会发现有问题

 出现问题的原因是,在BookServiceImpl类中添加了BookDao的属性,并提供了setter方法,但是 目前是没有提供配置注入BookDao的,所以bookDao对象为Null,调用其save方法就会报控指针异 常。

2.注解实现按照类型注入

对于这个问题使用注解该如何解决 ?
(1) BookServiceImpl 类的 bookDao 属性上添加 @Autowired 注解
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
// public void setBookDao(BookDao bookDao) {
// this.bookDao = bookDao;
// }
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
注意 :
@Autowired 可以写在属性上,也可也写在 setter 方法上,最简单的处理方式是 写在属性上并将
setter 方法删除掉
为什么 setter 方法可以删除呢 ?
  • 自动装配基于反射设计创建对象并通过暴力反射为私有属性进行设值
  • 普通反射只能获取public修饰的内容
  • 暴力反射除了获取public修饰的内容还可以获取private修改的内容
  • 所以此处无需提供setter方法

(2)@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 ..." + name);}
}@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而容器中也有一个bookDao,所以可以成功注入。
  • 分析下面这种情况是否能完成注入呢?

不行,因为按照类型会找到多个bean对象,此时会按照bookDao名称去找,因为IOC容器只有名称叫bookDao1bookDao2 ,所以找不到,会报NoUniqueBeanDefinitionException

3.注解实现按照名称注入

当根据类型在容器中找到多个 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 一起使用

4.简单数据类型注入

引用类型看完,简单类型注入就比较容易懂了。简单类型注入的是基本数据类型或者字符串类型,下面在BookDaoImpl 类中添加一个 name 属性,用其进行简单类型注入
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
private String name;
public void save() {
System.out.println("book dao save ..." + name);
}
}
数据类型换了,对应的注解也要跟着换,这次使用 @Value 注解,将值写入注解的参数中就行了
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
@Value("itheima")
private String name;
public void save() {
System.out.println("book dao save ..." + name);
}
}
注意数据格式要匹配,如将 "abc" 注入给 int 值,这样程序就会报错。
介绍完后,会有一种感觉就是这个注解好像没什么用,跟直接赋值是一个效果,还没有直接赋值简
单,所以这个注解存在的意义是什么 ?

5.注解读取properties配置文件

@Value一般会被用在从properties配置文件中读取内容进行使用,具体如何实现?

步骤 1 resource 下准备 properties 文件
jdbc.properties
 name=itheima888
步骤 2: 使用注解加载 properties 配置文件
在配置类上添加 @PropertySource 注解
@Configuration
@ComponentScan("com.itheima")
//@PropertySource加载properties配置文件
@PropertySource({"jdbc.properties"})
public class SpringConfig {
}
步骤 3 :使用 @Value 读取配置文件中的内容
@Repository("bookDao")public class BookDaoImpl implements BookDao {//@Value:注入简单类型(无需提供set方法)@Value("${name}")private String name;public void save() {System.out.println("book dao save ..." + name);}
}
步骤4:运行程序
运行 App 类,查看运行结果,说明配置文件中的内容已经被加载到

注意 :
  • 如果读取的properties配置文件有多个,可以使用@PropertySource的属性来指定多个
 @PropertySource({"jdbc.properties","xxx.properties"})
  • @PropertySource注解属性中不支持使用通配符* ,运行会报错
@PropertySource({"*.properties"})
  • @PropertySource注解属性中可以把classpath:加上,代表从当前项目的根路径找文件
@PropertySource({"classpath:jdbc.properties"})

      知识点 4 @PropertySource

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

前面定义 bean 的时候都是在自己开发的类上面写个注解就完成了,但如果是第三方的类,这些类都是在jar 包中,我们没有办法在类上面添加注解,这个时候该怎么办 ?
遇到上述问题,我们就需要有一种更加灵活的方式来定义 bean, 这种方式不能在原始代码上面书写注解,一样能定义bean, 这就用到了一个全新的注解 @Bean
这个注解该如何使用呢 ?
咱们把之前使用配置方式管理的数据源使用注解再来一遍,通过这个案例来学习下 @Bean 的使用。

1.环境准备

添加BookDaoBookDaoImpl

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

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

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 容器中 ?
针对这个问题,有两个解决方案 :

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 对象并打印控制台。
这种方式虽然能够扫描到,但是不能很快的知晓都引入了哪些配置类,所有这种方式不推荐使用。

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 {
}

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

在使用 @Bean 创建 bean 对象的时候,如果方法在创建的过程中需要其他资源该怎么办 ?
这些资源会有两大类,分别是 简单数据类型 引用数据类型

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;
}
}
注入简单数据类型步骤
步骤 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 {//1.定义一个方法获得要管理的对象@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;//2.添加@Bean,表示当前方法的返回值是一个bean@Beanpublic 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 就是键值对中的键的值

2.引用数据类型 

假设在构建 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;
}
}
注入引用数据类型步骤
步骤 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: 运行程序

三、注解开发总结

相关文章:

【Spring篇】IOC/DI注解开发

&#x1f353;系列专栏:Spring系列专栏 &#x1f349;个人主页:个人主页 目录 一、IOC/DI注解开发 1.注解开发定义bean 2.纯注解开发模式 1.思路分析 2.实现步骤 3.注解开发bean作用范围与生命周期管理 1.环境准备 2.Bean的作用范围 3.Bean的生命周期 4.注解开发依赖…...

1 Unix基础知识

1.1 登录 1.1 登录名 登录Unix系统时&#xff0c;要先输入登录名&#xff0c;然后再输入口令。系统再其口令文件&#xff08;/etc/password文件&#xff09;查看登录名。口令文件中的登录项由7个以冒号分隔的字段组成&#xff1a;登录名&#xff0c;加密口令&#xff0c;数字用…...

【翻译一下官方文档】认识uniCloud云数据库(基础篇)

我将用图文的形式&#xff0c;把市面上优质的课程加以自己的理解&#xff0c;详细的把&#xff1a;创建一个uniCloud的应用&#xff0c;其中的每一步记录出来&#xff0c;方便大家写项目中&#xff0c;做到哪一步不会了&#xff0c;可以轻松翻看文章进行查阅。&#xff08;此文…...

全局解释器锁 GIL

问题 你已经听说过全局解释器锁 GIL&#xff0c;担心它会影响到多线程程序的执行性能。 解决方案 尽管 Python 完全支持多线程编程&#xff0c;但是解释器的 C 语言实现部分在完全并行执行时并不是线程安全的。 实际上&#xff0c;解释器被一个全局解释器锁保护着&#xff…...

github 下载文件加速 https://moeyy.cn/gh-proxy/

GitHub文件链接带不带协议头都可以&#xff0c;支持release、archive以及文件&#xff0c;右键复制出来的链接都是符合标准的。 注意&#xff0c;不支持项目文件夹&#xff0c;请使用Git。 分支源码&#xff1a;https://github.moeyy.xyz/https://github.com/moeyy/project/arc…...

第五章 资源包使用

游戏开发中会大量使用模型文件&#xff0c;图片文件&#xff0c;这些资源都需要事先导入到项目中去。导入的方式非常简单&#xff0c;将这些文件直接复制到项目中的Assets目录下即可。Unity 会在文件添加到 Assets 文件夹时自动检测到这些文件并同步显示在Project视图中。 Uni…...

Linux od命令

Linux od命令用于输出文件内容。 od指令会读取所给予的文件的内容&#xff0c;并将其内容以八进制字码呈现出来。 语法 od [-abcdfhilovx][-A <字码基数>][-j <字符数目>][-N <字符数目>][-s <字符串字符数>][-t <输出格式>][-w <每列字符…...

【15】SCI易中期刊推荐——电子电气 | 仪器仪表(中科院4区)

💖💖>>>加勒比海带<<<💖💖 🍀🍀>>>【YOLO魔法搭配&论文投稿咨询】<<<🍀🍀 ✨✨>>>学习交流 | 温澜潮生 | 合作共赢 | 共同进步<<<✨✨ 📚📚>>>人工智能 | 计算机视觉 | 深度学习Tr…...

基于PaddleServing的串联部署 ocr 识别模型

要点&#xff1a; 使用paddleserving服务 1 首先需要安装PaddleServing部署相关的环境 PaddleServing是PaddlePaddle推出的一种高性能、易扩展、高可用的机器学习服务框架。PaddleOCR中使用PaddleServing主要是为了将训练好的OCR模型部署到线上环境&#xff0c;提供API服务&a…...

java OutputStream学习

1.概要 OutputStream位于java.io&#xff0c;它在Java 实现的IO类库中是一个很基础的抽象类。在层级上&#xff0c;是所有字节输出流类的父类&#xff0c;在功能上&#xff0c;表示接受字节并把它们输出。 2.实现类及子类简介 OutputStream有诸多子类&#xff1a; ByteAr…...

java 上传文件生成二进制流文件

最近在项目中遇到一个问题&#xff1a;需要将上传的文件生成输出流&#xff0c;然后将输出流转换为输入流上传到oss。 -------------------------------------------导出代码实现---------------------------------------------------------- ByteArrayOutputStream baos nu…...

质量小议22 -- 多少分合适

60分万岁~&#xff1f;&#xff1f;&#xff1f;&#xff01;&#xff01;&#xff01; 如果用分数评价质量&#xff0c;多少分合适&#xff1f;60&#xff0c;70&#xff0c;80...还是100&#xff0c;或者 120 对于质量的提升&#xff0c;是雪中送炭&#xff0c;还是锦上添…...

变频器参数设定说明

使用默贝克MT110-0R4-S2B实现下面的练习题&#xff1a; 1、先恢复出厂设置&#xff0c;再输入电机参数&#xff0c;选择静态调谐 2、两种运行模式&#xff1a;多段速&#xff08;8段&#xff09;和简易PLC&#xff08;4段&#xff09; 3、面板启停&#xff0c;运行模式通过外部…...

实用调试技巧

目录&#xff1a; 1.什么是bug&#xff1f; 2.调试是什么&#xff1f;有多重要&#xff1f; 3.debug和release的介绍 4.Windows环境调试介绍 5.一些调试的实例 6.如何写出好(易于调试)的代码 7.编程常见的错误 1.什么是bug&#xff1f; bug--->臭虫、虫子。 为什么含…...

谁是液冷行业真龙头?疯狂的液冷技术!

“人工智能领域AIGC”、“ChatGPT”、“数据特区”、“东数西算”、“数据中心”&#xff0c;可以说是2023年最热的概念&#xff0c;算力提升的背后&#xff0c;处理器的功耗越来越高&#xff0c;想发挥出处理器的最高性能&#xff0c;需要更高的散热效率。 算力井喷之下&…...

自动化运维工具之Ansible

目录 一、自动化运维 1、通过xshell自动化运维 2、Ansible简介 3、Ansible特点及优势 4、Ansible核心程序 5、Ansible工作原理及流程 6、部署Ansible自动化运维工具 7、Ansible常用模块 (1) ansible命令行模块 (2) command模块 (3) shell模块 (4) cron模块 (5) us…...

霍兰德人格分析雷达图

雷达图 Radar Chart 雷达图是多特性直观展示的重要方式 问题分析 霍兰德认为&#xff1a;人格兴趣与职业之间应有一种内在的对应关系 人格分类&#xff1a;研究型、艺术型、社会型、企业型、传统型、现实性 职业&#xff1a;工程师、实验员、艺术家、推销员、记事员、社会工…...

《Odoo开发者模式必知必会》—— 缘起

Odoo作为业界优秀的开源商务软件&#xff0c;在全球范围内拥有广泛的使用者。在领英国际&#xff0c;可以搜索到全球很多国家都有大量odoo人才需求的招聘信息。在国内&#xff0c;虽然已经有为数不少的企业&#xff0c;他们或者已经使用odoo&#xff0c;或者正在了解odoo&#…...

Java8的Options介绍

Java8引入了一个名为 Options 的新类&#xff0c;它是一个容器&#xff0c;可以保存单个值或根本不保存任何值。Optional目的是提供一种更优雅的方式来处理 null 值&#xff0c;这通常会导致NullPointerException。在这篇博客文章中&#xff0c;我们将探索如何在 Java8中使用 O…...

SpringBoot 多数据源及事务解决方案

1. 背景 一个主库和N个应用库的数据源&#xff0c;并且会同时操作主库和应用库的数据&#xff0c;需要解决以下两个问题&#xff1a; 如何动态管理多个数据源以及切换&#xff1f; 如何保证多数据源场景下的数据一致性(事务)&#xff1f; 本文主要探讨这两个问题的解决方案…...

tcpdump使用教程

一、概述 tcpdump是一个功能强大的&#xff0c;用于抓取网络数据包的命令行工具&#xff0c;与带界面的Wireshark一样&#xff0c;基于libpcap库构建。这篇文章主要介绍tcpdump的使用。关于如何使用tcpdump的资料中&#xff0c;最有用的就是tcpdump的两个手册。 tcpdump使用手…...

Zynq-7000、FMQL45T900的GPIO控制(五)---linux应用层配置GPIO输出控制

上文中详细阐述了对应原理图MIO/EMIO的编号&#xff0c;怎么计算获取linux下gpio的编号 本文涉及C代码上传&#xff0c;下载地址 Zynq-7000、FMQL45T900的GPIO控制c语言代码资源-CSDN文库 本文详细记录一下针对获取到gpio的编号&#xff0c;进行配置输出模式&#xff0c;并进…...

带你搞懂人工智能、机器学习和深度学习!

不少高校的小伙伴找我聊入门人工智能该怎么起步&#xff0c;如何快速入门&#xff0c;多长时间能成长为中高级工程师&#xff08;聊下来感觉大多数学生党就是焦虑&#xff0c;毕业即失业&#xff0c;尤其现在就业环境这么差&#xff09;&#xff0c;但聊到最后&#xff0c;很多…...

Android 11.0 framework中Launcher的启动流程分析

1.前言 在11.0的系统rom定制化开发中,在rom定制过程中,在对于开发默认Launcher功能,解决开机动画后黑屏,了解fallbackhome机制等等 对于launcher的启动流程来说很重要,接下来就来分析下launcher的启动流程 2.framework中Launcher的启动流程分析的核心类 frameworks/ba…...

2023年第十五届华中杯赛题C 题 空气质量预测与预警

2023年五一假期期间&#xff0c;数学建模竞赛就有四场&#xff0c;各种比赛各种需求应接不暇。因此&#xff0c;对于本次浅析有不足的地方欢迎大家指出。为了更好的帮助大家华中杯参赛&#xff0c;下面带来&#xff0c;C题详细版思路。由于C题的难度&#xff0c;注定选题人数将…...

Go官方指南(一)包、变量、函数

import "time" 获取当前系统时间&#xff1a;time.Now() 每个 Go 程序都是由包构成的 按照约定 &#xff0c;包名与导入路径的最后一个元素一致。例如&#xff0c;"math/rand"包中的源码均以 package rand 语句开始 在 Go 中&#xff0c;如果一个名字以…...

liunx笔记

快捷键 #移动到行首 ctrla #移动到行尾 ctrle #删除光标之前的字符 ctrlu #删除光标之后的字符 ctrlk #清屏 ctrll正则表达式 正则中普通常用的元字符 元字符功能.匹配除了换行符以外的任意单个字符*前导字符出现0次或连续多次.*任意长度字符^行首(以…开头)&#xff0c;如…...

vue3 封装ECharts组件

一、前言 前端开发需要经常使用ECharts图表渲染数据信息&#xff0c;在一个项目中我们经常需要使用多个图表&#xff0c;选择封装ECharts组件复用的方式可以减少代码量&#xff0c;增加开发效率。 ECharts图表大家应该用的都比较多&#xff0c;基础的用法就不细说了&#xff…...

Spring Security 6.0系列【30】授权服务器篇之JOSE规范

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.0.4 本系列Spring Security 版本 6.0.2 本系列Spring Authorization Server 版本 1.0.2 源码地址:https://gitee.com/pearl-organization/study-spring-security-demo 文章目录 1. 前言2. JOSE 规范3. JW…...

维度表设计原则

维度的作用一般是查询约束、分类汇总以及排序等&#xff0c;我们在进行维度表设计时&#xff0c;应当提前考虑&#xff1a; &#xff08;1&#xff09;维度属性尽量丰富&#xff0c;为数据使用打下基础 比如淘宝商品维度有近百个维度属性&#xff0c;为下游的数据统计、分析、…...