IOC/DI配置管理第三方bean及注解开发。
目录
一、IOC/DI 配置管理第三方bean
1、配置第三方bean
2、加载properties 文件
3、核心容器
二、注解开发
1、注解开发定义bean
2、纯注解开发模式
3、注解开发bean作用范围与生命周期管理
4、注解开发依赖注入
三、IOC/DI注解开发管理第三方bean
1、注解开发管理第三方bean
2、注解开发实现为第三方bean注入资源
一、IOC/DI 配置管理第三方bean
1、配置第三方bean
▶ 实现Druid管理
▷ 步骤1 : 导入`druid`的依赖
pom.xml中添加依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency>
▷ 步骤2 : 配置第三方bean
在applicationContext.xml配置文件中添加`DruidDataSource`的配置
<?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"> <!--管理DruidDataSource对象--> <bean class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/spring_db"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> </beans>
▷ 步骤3 : 从IOC容器中获取对应的bean对象
public class App { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); DataSource dataSource = (DataSource) ctx.getBean("dataSource"); System.out.println(dataSource); } }
▶ 实现C3P0管理
▷ 步骤1 : 导入`C3P0`的依赖
pom.xml中添加依赖
<dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency>
▷ 步骤2 : 配置第三方bean
在applicationContext.xml配置文件中添加配置
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_db"/> <property name="user" value="root"/> <property name="password" value="root"/> <property name="maxPoolSize" value="1000"/> </bean>
注意:
● ComboPooledDataSource的属性是通过setter方式进行注入
● 想注入属性就需要在ComboPooledDataSource类或其上层类中有提供属性对应的setter方法
● C3P0的四个属性和Druid的四个属性是不一样的▷ 注意:
● 数据连接池在配置属性的时候,除了可以注入数据库连接四要素外还可以配置很多其他的属性,具体都有哪些属性用到的时候再去查,一般配置基础的四个,其他都有自己的默认值
● Druid 和 C3P0在没有导入mysql驱动包的前提下,Druid不会报错,C3P0会报错,说明Druid在初始化的时候没有去加载驱动,而C3P0刚好相反
● Druid程序运行虽然没有报错,但是当调用DruidDataSource的getConnection()方法获取连接的时候,也会报找不到驱动类的错误。2、加载properties 文件
▶ 第三方bean属性化
▷ 步骤1 : 准备properties配置文件
resources下创建一个jdbc.properties文件,并添加对应的属性键值对
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db jdbc.username=root jdbc.password=root
▷ 步骤2 : 开启`context`命名空间
在applicationContext.xml中开`context`命名空间
<?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 http://www.springframework.org/schema/context/spring-context.xsd"> </beans>
▷ 步骤3 : 加载properties配置文件
在配置文件中使用`context`命名空间下的标签来加载properties配置文件
<context:property-placeholder location="jdbc.properties"/>
▷ 步骤4 : 完成属性注入
使用`${key}`来读取properties配置文件中的内容并完成属性注入
<?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 http://www.springframework.org/schema/context/spring-context.xsd"> <context:property-placeholder location="jdbc.properties"/> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> </beans>
▶ 读取单个属性
▷ 步骤1 : 在项目中添对应的类
BookDao和BookDaoImpl类,并在BookDaoImpl类中添加`name`属性与setter方法
public interface BookDao { public void save(); } public class BookDaoImpl implements BookDao { private String name; public void setName(String name) { this.name = name; } public void save() { System.out.println("book dao save ..." + name); } }
▷ 步骤2 : 完成配置文件的读取与注入
在applicationContext.xml添加配置,`bean的配置管理`、`读取外部properties`、`依赖注入`:
<?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 http://www.springframework.org/schema/context/spring-context.xsd"> <context:property-placeholder location="jdbc.properties"/> <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"> <property name="name" value="${jdbc.driver}"/> </bean> </beans>
▶ 注意事项
▷ 问题一 : 键值对的key为`username`引发的问题
1.在properties中配置键值对的时候,如果key设置为`username`
username=root666
2.在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 http://www.springframework.org/schema/context/spring-context.xsd"> <context:property-placeholder location="jdbc.properties"/> <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"> <property name="name" value="${username}"/> </bean> </beans>
3.运行后,在控制台打印的却不是`root666`,而是自己电脑的用户名。出现问题的原因是`<context:property-placeholder/>` 标签会加载系统的环境变量,而且环境变量的值会被优先加载。运行下面的代码查看系统的环境变量:
public static void main(String[] args) throws Exception{ Map<String, String> env = System.getenv(); System.out.println(env); }
解决方案
<context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/>
system-properties-mode : 设置为NEVER,表示不加载系统属性,就可以解决上述问题。
还有一个解决方案就是避免使用`username`作为属性的`key`。
▷ 问题二 : 当有多个properties配置文件需要被加载,该如何配置?
1.调整下配置文件的内容,在resources下添加`jdbc.properties`,`jdbc2.properties`,内容如下:
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db jdbc.username=root jdbc.password=root
jdbc2.properties
username=root666
2.修改applicationContext.xml
<!--方式一 --> <context:property-placeholder location="jdbc.properties,jdbc2.properties" system-properties-mode="NEVER"/>
● 方式一 : 可以实现,如果配置文件多的话,每个都需要配置
<!--方式二--> <context:property-placeholder location="*.properties" system-properties-mode="NEVER"/>
● 方式二 : `*.properties` 代表所有以properties结尾的文件都会被加载,可以解决方式一的问题,但是不标准
<!--方式三 --> <context:property-placeholder location="classpath:*.properties" system-properties-mode="NEVER"/>
● 方式三 : 标准的写法,`classpath:`代表的是从根路径下开始查找,但是只能查询当前项目的根路径
<!--方式四--> <context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>
● 方式四 : 不仅可以加载当前项目还可以加载当前项目所依赖的所有项目的根路径下的properties配置文件
▶ 小结
● 开启`context`命名空间:
● 加载properties配置文件:
<context:property-placeholder location="" system-properties-mode="NEVER"/>
● 在applicationContext.xml引入properties配置文件中的值:
${key}
3、核心容器
▶ 容器的创建方式
▷ 类路径下的XML配置文件:直接加载类路径下的文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
▷ 文件系统下的XML配置文件:需要写完整的系统路径
ApplicationContext ctx = new FileSystemXmlApplicationContext(" D:\\workspace\\spring\\spring_10_container\\ src\\main\\resources\\applicationContext.xml");
▶ bean 获取的三种方式
▷ 方式一 :这种方式存在的问题是每次获取的时候都需要进行类型转换
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
▷ 方式二:这种方式可以解决类型强转问题,但是参数又多加了一个。
BookDao bookDao = ctx.getBean("bookDao",BookDao.class);
▷ 方式三 : 这种方式就类似依赖注入中的按类型注入。必须要确保IOC容器中该类型对应的bean对象只能有一个。
BookDao bookDao = ctx.getBean(BookDao.class);
▶ 容器类层次结构
(1)在IDEA中双击`shift`,输入BeanFactory
(2)点击进入BeanFactory类,ctrl+h,就能查看到如下结构的层次关系
▶ BeanFactory的使用
▷ 使用BeanFactory来创建IOC容器的具体实现方式为:
public class AppForBeanFactory { public static void main(String[] args) { Resource resources = new ClassPathResource("applicationContext.xml"); BeanFactory bf = new XmlBeanFactory(resources); BookDao bookDao = bf.getBean(BookDao.class); bookDao.save(); } }
▷ 对比
● BeanFactory是延迟加载,只有在获取bean对象的时候才会去创建
● ApplicationContext是立即加载,容器加载的时候就会创建bean对象
● ApplicationContext要想成为延迟加载,只需要按照如下方式进行配置:(加上 lazy-init)
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" lazy-init="true"/>
▶ 总结
▷ 容器相关
● BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载
● ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载
● ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能
● ApplicationContext接口常用初始化类
○ ClassPathXmlApplicationContext(常用)
○ FileSystemXmlApplicationContext▷ bean相关
▷ 依赖注入相关
二、注解开发
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>
● 注意:
1、component-scan:
○ component : 组件,Spring将管理的bean视作自己的一个组件
○ scan:扫描2、base-package指定Spring框架扫描的包路径,它会扫描指定包及其子包中的所有类上的注解。
○ 包路径越多[如:com.itheima.dao.impl],扫描的范围越小速度越快
○ 包路径越少[如:com.itheima],扫描的范围越大速度越慢
○ 一般扫描到项目的组织名称即Maven的groupId下[如:com.itheima]即可。▷ 步骤4 : Service上添加注解
在BookServiceImpl类上也添加`@Component`交给Spring框架管理
@Component public class BookServiceImpl implements BookService { }
▷ 步骤5 : 运行程序
在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); } }
说明 :
● BookServiceImpl类没有起名称,所以在App中是按照类型来获取bean对象
● @Component注解如果不起名称,会有一个默认值就是`当前类名首字母小写`,所以也可以按照名称获取,如:
BookService bookService = (BookService)ctx.getBean("bookServiceImpl"); System.out.println(bookService);
● 对于@Component注解,还衍生出了其他三个注解`@Controller`、`@Service`、`@Repository`
通过查看源码会发现:(这三个注解和@Component注解的作用是一样的,为什么要衍生出这三个呢?为了方便我们后期在编写类的时候能很好的区分出这个类是属于`表现层`、`业务层`还是`数据层`的类。)
● @Component
2、纯注解开发模式
▶ 实现方式
首先将配置文件applicationContext.xml删除掉,使用类来替换。
▷ 步骤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) { 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.itheima.service","com.itheima.dao"})
● 读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象
//加载配置文件初始化容器 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); //加载配置类初始化容器 ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
● @Configuration
● @ComponentScan
3、注解开发bean作用范围与生命周期管理
▶ @Scope 注解
默认情况下bean是单例,要想变成非单例,只需要在其类上添加`@scope`注解,列如:
@Repository //@Scope设置bean的作用范围 @Scope("prototype") public class BookDaoImpl implements BookDao { public void save() { System.out.println("book dao save ..."); } }
▶ Bean的生命周期
● @PostConstruct
● @PreDestroy
● 注意 : @PostConstruct和@PreDestroy注解如果找不到,需要导入下面的jar包。找不到的原因是,从JDK9以后jdk中的javax.annotation包被移除了,这两个注解刚好就在这个包中。
<dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> </dependency>
例如:
@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 ..."); } }
要想看到两个方法执行,需要注意的是`destroy`只有在容器关闭的时候,才会执行。
▶ 小结
4、注解开发依赖注入
● @Autowired
▶ 添加依赖
pom.xml 添加Spring的依赖
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.10.RELEASE</version> </dependency> </dependencies>
▶ 注解实现按照类型注入
▷ (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 ..." ); } } @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`,所以可以成功注入。
● 分析下面这种情况是否能完成注入呢?
不行,因为按照类型会找到多个bean对象,此时会按照`bookDao`名称去找,因为IOC容器只有名称叫`bookDao1`和`bookDao2`,会找不到,会报`NoUniqueBeanDefinitionException`异常。
▶ 注解实现按照名称注入
● @Qualifier
当根据类型在容器中找到多个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一起使用。
▶ 简单数据类型注入
● @Value
简单类型注入的是基本数据类型或者字符串类型,下面在`BookDaoImpl`类中添加一个`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值,这样程序就会报错。
▶ 注解读取properties配置文件
● @PropertySource
▷ 步骤1:resource下准备properties文件
name=itheima888
▷ 步骤2 : 使用注解加载properties配置文件
在配置类上添加`@PropertySource`注解
@Configuration @ComponentScan("com.itheima") @PropertySource("jdbc.properties") public class SpringConfig { }
▷ 步骤3:使用@Value读取配置文件中的内容
@Repository("bookDao") public class BookDaoImpl implements BookDao { @Value("${name}") private String name; public void save() { System.out.println("book dao save ..." + name); } }
注意:
● 如果读取的properties配置文件有多个,可以使用`@PropertySource`的属性来指定多个
@PropertySource({"jdbc.properties","xxx.properties"})
● `@PropertySource`注解属性中不支持使用通配符`*`,运行会报错
@PropertySource({"*.properties"})
● `@PropertySource`注解属性中可以把`classpath:`加上,代表从当前项目的根路径找文件
@PropertySource({"classpath:jdbc.properties"})
三、IOC/DI注解开发管理第三方bean
● pom.xml添加Spring的依赖
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.10.RELEASE</version> </dependency> </dependencies>
1、注解开发管理第三方bean
● @Bean
▶ 实现步骤
▷ 步骤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); } }
▶ 引入外部配置类
● @Import
对于数据源的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.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; } }
▷ 使用`@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注解在配置类中只能写一次
2、注解开发实现为第三方bean注入资源
▶ 注入简单数据类型
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; } }
▶ 注入引用数据类型
▷ 步骤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定义方法设置形参即可,容器会根据类型自动装配对象。
▶ 总结