掌握纯注解开发依赖注入(DI)模式
学习使用纯注解进行第三方Bean注入
思考:如何使用注解方式将Bean对象注入到类中
@Service
public class StudentServiceImpl implements StudentService {
//创建成员对象
//@Autowired:注入引用类型,自动装配模式,默认按类型装配
@Autowired
private StudentDao studentDao ;
@Override
public void save() {
System.out.println("Service: 添加学生信息到数据库...");
studentDao.save();
}
}
说明:不管是使用配置文件还是配置类,都必须进行对应的Spring注解包扫描才可以使用。@Autowired默认按照类型自动装配,如果IoC容器中同类的Bean有多个,那么默认按照变量名和Bean的名称匹配,建议使用@Qualifier注解指定要装配的bean名称
注意:自动装配基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据,因此无需提供setter方法。
目的:解决IoC容器中同类型Bean有多个装配哪一个的问题
@Service
public class StudentServiceImpl implements StudentService {
//创建成员对象
//@Autowired:注入引用类型,自动装配模式,默认按类型装配
@Autowired
//@Qualifier:自动装配bean时按bean名称装配
@Qualifier("studentDaoImpl")
private StudentDao studentDao ;
@Override
public void save() {
System.out.println("Service: 添加学生信息到数据库...");
studentDao.save();
}
}
注意:@Qualifier注解无法单独使用,必须配合@Autowired注解使用
@Repository
public class StudentDaoImpl implements StudentDao {
//@Value:注入简单类型(无需提供set方法)
@Value("${test.name}")
private String name;
@Override
public void save() {
System.out.println("DAO: name= "+name);
System.out.println("DAO: 添加学生信息到数据库...");
}
}
以上@Value注解中使用${test.name}从属性文件中读取test.name值,那么就需要在配置类或者配置文件中加载属性文件。
@Configuration
@ComponentScan("com.itheima")
//@PropertySource加载properties配置文件
@PropertySource("classpath:test.properties") //如果是多个属性文件,则使用{}数组
public class SpringConfig {
}
注意:@PropertySource中加载多文件请使用数组格式配置,不允许使用通配符*
思考:导入自己定义的配置类有几种方式?
mysql
mysql-connector-java
8.0.30
com.alibaba
druid
1.2.18
package com.zbbmeta.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class JdbcConfig {
//@Bean:表示当前方法的返回值是一个bean对象,添加到IOC容器中
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_druid");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
@Configuration // 指定这个类为配置类,替代application.xml
@ComponentScan("com.zbbmeta")//代替
@PropertySource("classpath:test.properties") //如果是多个属性文件,则使用{}数组
@Import(JdbcConfig.class) //加载JdbcConfig配置类
public class SpringConfig {
}
JdbcConfig类上添加注解
@Configuration
public class JdbcConfig {
//@Bean:表示当前方法的返回值是一个bean对象,添加到IOC容器中
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_druid");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
SpringConfig配置不变
@Configuration // 指定这个类为配置类,替代application.xml
@ComponentScan("com.zbbmeta")//代替
@PropertySource("classpath:test.properties") //如果是多个属性文件,则使用{}数组
//@Import(JdbcConfig.class) //加载JdbcConfig配置类
public class SpringConfig {
}
思考:配置类中如何注入简单类型数据,如何注入引用类型数据?
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;
//1.定义一个方法获得要管理的对象
//2.@Bean:表示当前方法的返回值是一个bean对象,添加到IOC容器中
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}
}
说明:如果@Value()中使用了EL表达式读取properties属性文件中的内容,那么就需要加载properties属性文件。
//Spring会自动从IOC容器中根据类型找到StudentDao对象赋值给参数studentDao变量,如果没有就会报错。
@Bean
public DataSource dataSource(StudentDao studentDao){
System.out.println("JdbcConfig studentDao = " + studentDao);
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}
注意:引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象
@Test
public void testDatasource() throws SQLException {
//目标:从IOC容器中获取德鲁伊连接池对象
//1.AnnotationConfigApplicationContext加载Spring配置类初始化Spring容器
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
//按类型获取bean
DataSource dataSource = ac.getBean(DataSource.class);
Connection connection = dataSource.getConnection();
//3.打印对象
System.out.println("连接池对象:"+dataSource);
System.out.println("连接象地址:"+connection);
//4.关闭容器
ac.close();
}