文章目录
- 1. 用注解开发定义bean
- 2. 纯注解开发
- 3. 注解开发的 bean 管理
- 3.1 作用范围管理(单例或非单例)
- 3.2 生命周期管理
- 4. 注解开发的依赖注入
- 4.1 引用类型的依赖注入
- 4.2 简单类型的依赖注入
- 4.2.1 直接注入值
- 4.2.2 注入 properties 文件中的值
- 5. 注解开发与第三方 bean
- 5.1 管理第三方 bean
- 5.2 为第三方 bean 注入资源
- 5.2.1 注入简单类型
- 5.2.2 注入引用类型
- 6. xml 配置 VS 注解配置
1. 用注解开发定义bean
@Component("bookDao")//相当于配置了bean,并指定了id
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("book dao save...");
}
}
//相当于配置了bean,但未指定id
//这里还没有 bookDao 的依赖注入,后面会讲到
@Component
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
@Override
public void save() {
System.out.println("book service save...");
bookDao.save();
}
}
<?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">
<!--1. 开启context命名空间-->
<!--让配置文件能够扫描到类上的注解-->
<!--base-package="com.itheima":扫描com.itheima下的所有类-->
<context:component-scan base-package="com.itheima"/>
</beans>
public class AnnotationBeanApp {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
System.out.println(bookDao);
//没有id,按类型取
BookService bookService = ctx.getBean(BookService.class);
System.out.println(bookService);
}
}
输出结果:
com.itheima.dao.impl.BookDaoImpl@5e4c8041
com.itheima.service.impl.BookServiceImpl@fdefd3f
Spring 提供了 @Component 注解的三个衍生注解:
@Controller:用于表现层(servelt) bean 定义
@Service:用于业务层(service) bean 定义
@Repository:用于数据层(dao) bean 定义
有了上面三个衍生注解,BookDaoImpl 的 bean 可以用 @Repository 配置,BookServiceImpl 的 bean 可以用 @Service 配置。这样增强可读性。
2. 纯注解开发
Spring 3.0 升级了纯注解开发模式,使用 Java 类替代配置文件,开启了 spring 快速开发赛道。
(1) 类上的注解与上节相同
@Component("bookDao")//相当于配置了bean,并指定了id
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("book dao save...");
}
}
//相当于配置了bean,但未指定id
//这里还没有 bookDao 的依赖注入,后面会讲到
@Component
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
@Override
public void save() {
System.out.println("book service save...");
bookDao.save();
}
}
(2) 用一个配置类代替配置文件的功能:新建配置类,并告诉配置类扫描哪个目录下的 bean。
(3) 加载配置时有所不同,其余都与上节相同
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);
//没有id,按类型取
BookService bookService = ctx.getBean(BookService.class);
System.out.println(bookService);
}
}
输出结果:
com.itheima.dao.impl.BookDaoImpl@255b53dc
com.itheima.service.impl.BookServiceImpl@4f9a3314
@Configuration 注解用于设定当前类为配置类
@ComponentScan 注解用于设定扫描路径,此注解只能添加一次,多个数据用数组格式
@ComponentScan({"com.itheima.service","com.itheima.dao"})
3. 注解开发的 bean 管理
3.1 作用范围管理(单例或非单例)
@Scope(“singleton”):单例
@Scope(“prototype”):非单例
默认单例
@Repository("bookDao")
@Scope("prototype")//非单例
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("book dao save...");
}
}
3.2 生命周期管理
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("book dao save...");
}
@PostConstruct//在构造方法后执行
public void init(){
System.out.println("init...");
}
@PreDestroy//在bean销毁前执行
public void destroy(){
System.out.println("destory...");
}
}
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao1 = (BookDao) ctx.getBean("bookDao");
BookDao bookDao2 = (BookDao) ctx.getBean("bookDao");
System.out.println(bookDao1);
System.out.println(bookDao2);
ctx.close();//关闭容器,以执行bean的销毁方法
}
}
输出结果:
init...
com.itheima.dao.impl.BookDaoImpl@62e136d3
com.itheima.dao.impl.BookDaoImpl@62e136d3
destory...
4. 注解开发的依赖注入
4.1 引用类型的依赖注入
(1) 按类型装配@Autowired
@Repository//相当于配置了bean(创建对象)
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("book dao save...");
}
}
@Service//相当于配置了bean(创建对象)
public class BookServiceImpl implements BookService {
@Autowired//按类型装配
private BookDao bookDao;
//不需要set方法了
// public void setBookDao(BookDao bookDao) {
// this.bookDao = bookDao;
// }
@Override
public void save() {
System.out.println("book service save...");
bookDao.save();
}
}
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookService bookService = ctx.getBean(BookService.class);
bookService.save();
}
}
输出结果:
book service save...
book dao save...
(2) 按名称装配
@Autowired
@Qualifier("bookDao2")
在(1)的例子中,若同时有:
@Repository("bookDao1")
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("book dao save...");
}
}
@Repository("bookDao2")
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("book dao save...");
}
}
则按类型装配就不行了,此时可以按名称装配。
@Autowired//不可省略
@Qualifier("bookDao2")//按名称装配
private BookDao bookDao;
输出结果:
book service save...
book dao save2...
【注意】
- 自动装配基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据,因此无需提供 setter 方法。
- 自动装配建议使用无参构造方法创建对象(默认),如果不提供对应构造方法,请提供唯一的构造方法。
- @Qualifier 注解无法单独使用,必须配合 @Autowired 注解使用。
4.2 简单类型的依赖注入
4.2.1 直接注入值
@Value("itheima")
private String name;
4.2.2 注入 properties 文件中的值
(1) jdbc.properties
name=itheima888
(2) 在配置类 SpringConfig.java 中加载 properties 文件
【注】多文件应使用数组格式配置@PropertySource({"jdbc1.properties","jdbc2.properties"})
不允许使用通配符,*.properties
、classpath*:jdbc.properties
都不行,classpath:jdbc.properties
可以。
(3) 注入值
5. 注解开发与第三方 bean
5.1 管理第三方 bean
方式1:在配置类中直接获取第三方 bean。
@Configuration
public class SpringConfig {
// 1.定义一个方法,获取要管理的对象
// 2.添加@bean,表示当前方法的返回值是一个bean
@Bean//可以写成@Bean("dataSource")
public DataSource dataSource(){//方法名建议:要管理的bean的id名称
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;
}
}
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,配置类会十分庞大。
方式 2:新建 JdbcConfig 类,将获取第三方 bean 的方法剪切到该类中,并添加 @Configuration 注解。
为 SpringConfig 添加扫描 bean 的注解
@Configuration
@ComponentScan("com.itheima.config")//扫描bean
public class SpringConfig {
}
但是,该方法也不推荐,因为 JdbcConfig 类上也有 @Configuration 注解,显得有点乱;而且通过 SpringConfig 上的 @ComponentScan(“com.itheima.config”) 也看不出到底加载了哪些注解。
方式 3:去掉 JdbcConfig 上的 @Configuration 注解,用 @Import 引入。
引入多个类时,用数组:@Import({JdbcConfig.class,JdbcConfig1.class})
5.2 为第三方 bean 注入资源
5.2.1 注入简单类型
为第三方 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("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;
}
}
5.2.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("root")
private String password;
//检测到该方法要配置一个bean,就认为需要提供形参,所以bookDao进行了自动装配
@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;
}
}
@Repository
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("book dao save...");
}
}
@Configuration
@ComponentScan("com.itheima")//扫描bookDao
@Import(JdbcConfig.class)
public class SpringConfig {
}
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);
}
}
输出结果:
com.itheima.dao.impl.BookDaoImpl@7bd4937b
{
CreateTime:"2023-01-28 21:08:42",
ActiveCount:0,
PoolingCount:0,
CreateCount:0,
DestroyCount:0,
CloseCount:0,
ConnectCount:0,
Connections:[
]
}
6. xml 配置 VS 注解配置
红色标注的是十分常用的。