Spring 通过配置文件加载 Bean
开始本文的内容之前你得要搭建好 Spring 源码的环境,不会搭建的可以去查阅查阅我之前写的 Spring源码编译:
在 resources 当中创建配置文件 spring-config.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"> </beans>
在配置文件当中添加配置:
<bean id="userService" class="top.it6666.service.UserServiceImpl"/>
在工程当中创建业务类:
UserService.java
/** * @author yby6 * @program spring * @date Created in 2023/9/29 029 11:39 * @description **/ public interface UserService { /** * 显示 */ void show(); }
UserServiceImpl.java
/** * @author yby6 * @program spring * @date Created in 2023/9/29 029 11:40 * @description **/ public class UserServiceImpl implements UserService { @Override public void show() { System.out.println("Hello Spring"); } }
验证
在测试类当中,编写创建容器,获取 Bean,进行测试:
/** * @author yby6 * @program spring * @date Created in 2023/9/29 029 11:42 * @description **/ public class SpringTest { public static void main(String[] args) { ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:spring-config.xml"); UserService userService = (UserService) applicationContext.getBean("userService"); userService.show(); } }
Spring 通过注解加载 Bean
在测试类上添加注解 @Configuration
与 包扫描
:
在业务类上方添加 Spring 相关注解注入到 Spring IOC 容器当中:
验证
更改之前的测试类,通过注解加载容器,获取 Bean 元素:
public static void main(String[] args) { // 通过注解获取容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringTest.class); UserService userService = (UserService) applicationContext.getBean("userServiceImpl"); userService.show(); UserController userController = (UserController) applicationContext.getBean("userController"); userController.showMethod(); System.out.println("==========================="); // 扩展内容,可以通过上下文对象获取所有管理的Bean name,通过getBeanDefinitionNames()获取 String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); for (String beanDefinitionName : beanDefinitionNames) { System.out.println(beanDefinitionName); } }
整体流程,解析配置,定位与注解对象,注入对象,无论是通过 xml 还是注解的方式都需要经过解析和加载然后在注入对象放入到 IOC 容器当中
Spring 中常见配置
关于 bean:
在 Spring 当中一切都是围绕 Bean
进行,Bean 本质就是 Java 对象, 平时由我们自己来进行创建, 有了 Spring 后, Bean 的创建全部交给了 Spring,不需要在原来创建 Bean 的地方添加任何的额外信息,这些额外的信息全部通过配置文件进行控制。
关于:BeanDefinition,在 Spring 运行过程当中,会根据配置生成用来描述 Bean 的 BeanDefinition
。
作用范围
- @Scope
关于取值:
- singleton
- prototype
- request
- session
- globalsession
懒加载
- @Lazy
定义 Bean 是否为延时加载, 如果为 true 会在真正使用 Bean 的时候才加载
首选
- @Primary
值为 true,Bean 会优先实现类,如果按照类型装配时,如果存在一个接口对应多个实现类,多个实现类中被 Primary 为 true 的类会优先当做接口的实现类进行装配
还可以通过 Factory-bean 和 Factory-method(@configuration 和 @Bean) 从工厂 Bean 或工厂方法当中获取 Bean。
Bean 配置演示
创建 entity 包,在该包中创建实体类 Student:
在 xml 配置文件当中添加配置:
<bean id="student" class="top.it6666.entiry.Student" scope="singleton" />
验证:
public static void main(String[] args) { ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:spring-config.xml"); for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) { System.out.println(beanDefinitionName); } Student student1 = (Student) applicationContext.getBean("student"); Student student2 = (Student) applicationContext.getBean("student"); System.out.println(student1); System.out.println(student2); }
如上的 bean 配置添加了 scope 并且配置为了单例所以创建出来的对象内存地址都是同一个,在来看看 Primary 当一个接口存在多个实现类会优先注入为 true 的实现类,先来看这一点吧,再次新建一个实现类 QqUserServiceImpl.java:
/** * @author yby6 * @program spring * @date Created in 2023/9/28 028 14:28 * @description **/ @Service public class QqUserServiceImpl implements UserService { @Override public void show() { System.out.println("QQ用户"); } }
修改 xml 添加配置:
<bean id="qqUserService" class="top.it6666.service.QqUserServiceImpl" primary="true" />
验证方式:
public static void main(String[] args) { ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:spring-config.xml"); UserService userService = applicationContext.getBean(UserService.class); userService.show(); }
关于懒加载,目前利用 UserServiceImpl.java 测试懒加载,明确的实现 UserServiceImpl.java 的默认无参构造函数,在当中加一句打印代码:
紧接着修改 xml 配置文件添加懒加载配置,然后我们在运行测试类代码进行测试,如果打印了刚刚我们添加的打印信息就说明 Spring 已经加载了,没有打印就说明没有其他地方使用该资源,没有进行加载:
<bean id="userService" class="top.it6666.service.UserServiceImpl" lazy-init="true"/>
运行测试类:
并没有打印我们添加的日志信息所以说明没有加载,已经达到了懒加载效果,也就是延时加载的效果,我们在来看看使用了 UserServiceImpl.java 之后它的效果又是如何呢修改 QqUserServiceImpl.java:
/** * @author yby6 * @program spring * @date Created in 2023/9/28 028 14:28 * @description **/ @Service public class QqUserServiceImpl implements UserService { private UserServiceImpl userServiceImpl; public void setUserServiceImpl(UserServiceImpl userServiceImpl) { this.userServiceImpl = userServiceImpl; } public UserServiceImpl getUserServiceImpl() { return this.userServiceImpl; } @Override public void show() { System.out.println("QQ用户"); } }
在 xml 当中进行属性注入:
<bean id="qqUserService" class="top.it6666.service.QqUserServiceImpl" primary="true" > <property name="userServiceImpl" ref="userService"/> </bean>
运行测试类代码:
创建 factory
包,在该包下创建 StudentFactory
类:
/** * @author yby6 * @program spring * @date Created in 2023/9/28 028 14:00 * @description **/ public class StudentFactory { public static Student getStudent() { return new Student(); } }
使用静态工厂创建实例(factory-method):
<bean id="student" class="top.it6666.factory.StudentFactory" factory-method="getStudent" scope="singleton" />
验证方式同上:
使用 FacotoryBean 创建对象
在 factory 包中创建 StudentFacotory,其实在如上我们已经创建该类,不一样的就是类当中 getStudent 方法是静态的,现在我们改为非静态方法如下:
创建过程,需要先创建 FactoryBean 对象,再通过该对象调用里面的方法进行创建 Bean。
<bean id="studentFactory" class="top.it6666.factory.StudentFactory"/> <bean id="studentThree" factory-bean="studentFactory" factory-method="getStudent" />
测试验证一下,测试结果如下:
目前还没有讲解到关于 Spring IOC 源码的边缘,因为博主的想法就是想将该内容分为许多的小文章进行一一发布,所以这里就先简单的介绍一下 IOC 相关的内容就相当于一个回顾吧
最后
本期结束咱们下次再见👋~
🌊 关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下哟~ 💗