Spring |(五)IoC/DI的注解开发
文章目录
- 📚核心容器
- 🐇环境准备
- 🐇容器的创建方式
- 🐇bean的三种获取方式
- 🐇BeanFactory的使用
- 📚IoC/DI注解开发
- 🐇环境准备
- 🐇注解开发定义bean
- 🐇纯注解开发模式
- 🐇bean的作用范围
- 🐇bean的生命周期
- 📚小结
学习来源:黑马程序员SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术
📚核心容器
🐇环境准备
- 创建一个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类
public interface BookDao { public void save(); } public class BookDaoImpl implements BookDao { public void save() { System.out.println("book dao 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(); } }
- 类路径下的XML配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
- 文件系统下的XML配置文件(不推荐使用)
ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\spring\\spring_10_container\\src\\main\\resources\\applicationContext.xml");
🐇bean的三种获取方式
-
方式一:
getBean("名称")
(存在的问题是每次获取时都需要进行类型转换)BookDao bookDao = (BookDao) ctx.getBean("bookDao");
-
方式二:
getBean("名称",类型.class)
(可以解决类型强转问题,但参数又多加了一个)BookDao bookDao = ctx.getBean("bookDao",BookDao.class);
-
方式三:
getBean(类型.class)
(类似于按类型注入,但要确保IoC容器中该类型对应的bean对象只能有一个)BookDao bookDao = ctx.getBean(BookDao.class);
🐇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
和ApplicationContext
之间的区别,在BookDaoImpl添加如下构造函数:public class BookDaoImpl implements BookDao { public BookDaoImpl() { System.out.println("constructor"); } public void save() { System.out.println("book dao save ..." ); } }
- 如果不去获取bean对象,打印会发现:
- BeanFactory是延迟加载,只有在获取bean对象的时候才会去创建。
- ApplicationContext是立即加载,容器加载的时候就会创建bean对象。
- ApplicationContext要想成为延迟加载,只需要按照如下方式进行配置(了解即可)。
<?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" lazy-init="true"/> </beans>
- BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载。
- ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载。
- ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能。
- ApplicationContext接口常用初始化类
- ClassPathXmlApplicationContext(常用)
- FileSystemXmlApplicationContext
📚IoC/DI注解开发
🐇环境准备
-
创建一个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(); } }
🐇注解开发定义bean
- 步骤1:删除原XML配置。把配置文件中的
<bean>
标签删掉。<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
- 步骤2:Dao上添加注解,在BookDaolmpl类上添加
@Component
注解。@Component("bookDao") public class BookDaoImpl implements BookDao { public void save() { System.out.println("book dao save ..." ); } }
- 注意:
@Component
注解不可以添加在接口上,因为接口是无法创建对象的。
- 注意:
- 步骤3:在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(); } }
@Component
注解如果不起名称,即直接就是@Component
而不是类似于@Component("bookDao")
,默认值就是当前类名首字母小写。
- 步骤4:配置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],扫描的范围越大速度越慢。
- 一般扫描到项目的组织名称即Maven的groupId下[如:com.itheima]即可。
- component-scan
- 步骤5:运行程序。
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); } }
- 衍生的三个注解
@Controller
、@Service
、@Repository
,这三个注解和@Component
注解的作用是一样的,目的是方便我们后期在编写类时能很好的区分出这个类是属于表现层、业务层还是数据层的类。@Controller
注解用于标识一个类为控制器(Controller),主要用于处理用户的请求并返回相应的视图。通常用于Spring MVC框架中,处理Web请求,并将处理结果返回给用户。@Service
注解用于标识一个类为服务(Service),主要用于定义业务逻辑的处理。它在应用程序中起到了事务边界的作用,将业务逻辑从控制器中分离出来,使得代码更加清晰和可维护。@Repository
注解用于标识一个类为存储库(Repository),主要用于与数据库或其他持久化机制进行交互。它通常是用于访问和操作数据库的接口,提供了一些常用的持久化方法,如增删改查。
🐇纯注解开发模式
Spring3.0开启了纯注解开发模式,使用Java类替代配置文件,开启了Spring快速开发赛道。
- 步骤1:创建一个配置类
SpringConfig
,并在该配置类上添加@Configuration
注解,替换applicationContext.xml
。 - 步骤2:再添加包扫描注解
@ComponentScan
替换<context:component-scan base-package=""/>
@Configuration @ComponentScan("com.itheima") public class SpringConfig { }
@ComponentScan
注解用于设定扫描路径,只能添加一次,多个数据用数组格式。@ComponentScan({com.itheima.service","com.itheima.dao"})
- 步骤3:创建一个新的运行类
AppForAnnotation
,读取Spring核心配置文件初始化容器对象【切换为】读取Java配置类初始化容器对象,并运行。public class AppForAnnotation { public static void main(String[] args) { //加载配置文件初始化容器 //ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); //加载配置类初始化容器 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); } }
🐇bean的作用范围
- 默认情况下bean是单例,要想变成非单例,需要在其类上添加
@scope
注解。@Repository //@Scope设置bean的作用范围 @Scope("prototype") public class BookDaoImpl implements BookDao { public void save() { System.out.println("book dao save ..."); } }
🐇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 ..."); } }
-
步骤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 ..."); } }
-
步骤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(); //关闭容器 } }
-
注意:
@PostConstruct
和@PreDestroy
注解如果找不到,需要导入下面的jar包,因为从JDK9以后jdk中的javax.annotation包被移除了,这两个注解刚好就在这个包中。<dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> </dependency>
📚小结
-
知识点1:@Component等
-
知识点2:@Configuration
-
知识点3:@ComponentScan
-
知识点4:@Scope
-
知识点5:@PostConstruct
-
知识点6:@PreDestroy