欢迎大家回到《 Java教程之Spring30天快速入门》,本教程所有示例均基于Maven实现,如果您对Maven还很陌生,请移步本人的博文《 如何在windows11下安装Maven并配置以及 IDEA配置Maven环境》,本文的上一篇为《 IOC/DI配置管理第三方bean && 加载properties文件》。

 Spring的IOC/DI对应的配置开发就已经讲解完成,但是使用起来相对来说还是比较复杂的,复杂的地方在配置文件。
 前面咱们聊Spring的时候说过,Spring可以简化代码的开发,到现在并没有体会到。
 所以Spring到底是如何简化代码开发的呢?
 要想真正简化开发,就需要用到Spring的注解开发,Spring对注解支持的版本历程:
- 2.0版开始支持注解
 - 2.5版注解功能趋于完善
 - 3.0版支持纯注解开发
 
关于注解开发,我们会讲解两块内容注解开发定义bean和纯注解开发。
 注解开发定义bean用的是2.5版提供的注解,纯注解开发用的是3.0版提供的注解。
1 环境准备
在学习注解开发之前,先来准备下案例环境:
- 创建一个Maven项目
 - pom.xml添加Spring的依赖
 
<dependencies>
	<dependency>
		<groupId>org.springframeworkgroupId>
		<artifactId>spring-contextartifactId>
		<version>5.2.10.RELEASEversion>
	dependency>
dependencies>
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 
- resources下添加applicationContext.xml
 
<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>
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 
- 添加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 ...");
	}
}
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 
- 创建运行类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
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 
最终创建好的项目结构如下:
 
2 注解开发定义bean
在上述环境的基础上,我们来学一学Spring是如何通过注解实现bean的定义开发?
 步骤1:删除原XML配置
 将配置文件中的标签删除掉
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
- 1
 
步骤2:Dao上添加注解
 在BookDaoImpl类上添加@Component注解
@Component("bookDao")
public class BookDaoImpl implements BookDao {
	public void save() {
		System.out.println("book dao save ..." );
	}
}
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 
注意:@Component注解不可以添加在接口上,因为接口是无法创建对象的。
 XML与注解配置的对应关系:
 
 步骤3:配置Spring的注解包扫描
 为了让Spring框架能够扫描到写在类上的注解,需要在配置文件上进行包扫描
<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
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 
说明:
 component-scan
- component:组件,Spring将管理的bean视作自己的一个组件
 - scan:扫描
 
base-package指定Spring框架扫描的包路径,它会扫描指定包及其子包中的所有类上的注解。
- 包路径越多[如:com.itheima.dao.impl],扫描的范围越小速度越快
 - 包路径越少[如:com.itheima],扫描的范围越大速度越慢
 - 一般扫描到项目的组织名称即Maven的groupId下[如: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();
	}
}
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 
步骤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);
	}
}
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 
打印观察结果,两个bean对象都已经打印到控制台
 
 说明:
- BookServiceImpl类没有起名称,所以在App中是按照类型来获取bean对象
 - @Component注解如果不起名称,会有一个默认值就是当前类名首字母小写,所以也可以按照名称获取,如:
 
BookService bookService = (BookService)ctx.getBean("bookServiceImpl");
System.out.println(bookService);
- 1
 - 2
 
对于@Component注解,还衍生出了其他三个注解@Controller、@Service、@Repository
 通过查看源码会发现:
 
 这三个注解和@Component注解的作用是一样的,为什么要衍生出这三个呢?
 方便我们后期在编写类的时候能很好的区分出这个类是属于表现层、业务层还是数据层的类。
 知识点1:@Component等
 
3 纯注解开发模式
上面已经可以使用注解来配置bean,但是依然有用到配置文件,在配置文件中对包进行了扫描,Spring在3.0版已经支持纯注解开发
- Spring3.0开启了纯注解开发模式,使用Java类替代配置文件,开启了Spring快速开发赛道
 
具体如何实现?
3.1 思路分析
实现思路为:
- 将配置文件applicationContext.xml删除掉,使用类来替换。
 
3.2 实现步骤
步骤1:创建配置类
 创建一个配置类SpringConfig
public class SpringConfig {
}
- 1
 - 2
 
步骤2:标识该类为配置类
 在配置类上添加@Configuration注解,将其标识为一个配置类,替换applicationContext.xml
@Configuration
public class SpringConfig {
}
- 1
 - 2
 - 3
 
步骤3:用注解替换包扫描配置
 在配置类上添加包扫描注解@ComponentScan替换
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}
- 1
 - 2
 - 3
 - 4
 
步骤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);
	}
}
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 
运行AppForAnnotation,可以看到两个对象依然被获取成功
 
 至此,纯注解开发的方式就已经完成了,主要内容包括:
- Java类替换Spring核心配置文件
 

- @Configuration注解用于设定当前类为配置类
 - @ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式
 
@ComponentScan({com.itheima.service","com.itheima.dao"})
- 1
 
- 读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象
 
//加载配置文件初始化容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//加载配置类初始化容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
- 1
 - 2
 - 3
 - 4
 
知识点1:@Configuration
 
 知识点2:@ComponentScan
 
 小结:
 这一节重点掌握的是使用注解完成Spring的bean管理,需要掌握的内容为:
- 记住@Component、@Controller、@Service、@Repository这四个注解
 - applicationContext.xml中context:component-san/的作用是指定扫描包路径,注解为@ComponentScan
 - @Configuration标识该类为配置类,使用类替换applicationContext.xml文件
 - ClassPathXmlApplicationContext是加载XML配置文件
 - AnnotationConfigApplicationContext是加载配置类
 
3.3 注解开发bean作用范围与生命周期管理
使用注解已经完成了bean的管理,接下来按照前面所学习的内容,将通过配置实现的内容都换成对应的注解实现,包含两部分内容: bean作用范围和bean生命周期。
3.3.1 环境准备
老规矩,学习之前先来准备环境:
- 创建一个Maven项目
 - pom.xml添加Spring的依赖
 
<dependencies>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>5.2.10.RELEASE</version>
	</dependency>
</dependencies>
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 
- 添加一个配置类SpringConfig
 
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}
- 1
 - 2
 - 3
 - 4
 
- 添加BookDao、BookDaoImpl类
 
public interface BookDao {
	public void save();
}
@Repository
public class BookDaoImpl implements BookDao {
	public void save() {
		System.out.println("book dao save ..." );
	}
}
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 
- 创建运行类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);
	}
}
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 
最终创建好的项目结构如下:
 
3.3.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 ...");
	}
}
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 
再次执行App类,打印结果:
 
 知识点1:@Scope
 
3.3.3 Bean的生命周期
(1)在BookDaoImpl中添加两个方法,init和destroy ,方法名可以任意
@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 ...");
	}
}
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 
(2)如何对方法进行标识,哪个是初始化方法,哪个是销毁方法?
 只需要在对应的方法上添加@PostConstruct和@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 ...");
	}
}
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 
(3)要想看到两个方法执行,需要注意的是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(); //关闭容器
	}
}
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 
(4)运行App,类查看打印结果,证明init和destroy方法都被执行了。

 注意:@PostConstruct和@PreDestroy注解如果找不到,需要导入下面的jar包
<dependency>
	<groupId>javax.annotationgroupId>
	<artifactId>javax.annotation-apiartifactId>
	<version>1.3.2version>
dependency>
- 1
 - 2
 - 3
 - 4
 - 5
 
找不到的原因是,从JDK9以后jdk中的javax.annotation包被移除了,这两个注解刚好就在这个包中。
 知识点1:@PostConstruct
 
 知识点2:@PreDestroy
 
 小结
 
 PS:由于篇幅的原因。纯注解开发模式下的依赖注入,我们在下一节再讲
          
              微信名片
            
        
                                    
评论记录:
回复评论: