Spring Framework 源码学习笔记(六)

简介: Spring Framework 源码学习笔记(六)

Chapter 06 - @Autowire 及 Aware

Section 01 -  @Autowire的位置

@Autowire出了可以放在属性上,还可以放置的setter方法上以及有参构造方法上,都可以实现Bean的自动装配

@Autowire在Setter方法上首先给两个实体类增加@Component注解,给User增加一个Address的属性

@Component
public class User {
    private String username;
    private String password;
    private Address address;
    public User() {
        System.out.println("User 无参数构造方法被调用");
    }
    public Address getAddress() {
        return address;
    }
    @Autowired
    public void setAddress(Address address) {
        this.address = address;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + ''' +
                ", password='" + password + ''' +
                ", address=" + address +
                '}';
    }
}
复制代码
@Component
public class Address {
    private Integer id;
    private String addressDetail;
    public Address() {
        System.out.println("Address空参构造方法被调用");
    }
    public Address(Integer id, String addressDetail) {
        System.out.println("Address有参数构造方法被调用");
        this.id = id;
        this.addressDetail = addressDetail;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getAddressDetail() {
        return addressDetail;
    }
    public void setAddressDetail(String addressDetail) {
        this.addressDetail = addressDetail;
    }
    @PostConstruct
    public void init(){
        System.out.println("Address Bean 的初始化方法");
    }
    @PreDestroy
    public void destroy(){
        System.out.println("Address Bean的销毁方法");
    }
}
复制代码

在BeanAutoAssembleConfig配置扫描entity包,将User和Address注册到容器中

@ComponentScan(basePackages = {"com.citi.dao","com.citi.service","com.citi.controller","com.citi.entity"})
public class BeanAutoAssembleConfig {
    //@Primary
    @Bean("personDao2")
    public PersonDao personDao(){
        return new PersonDao();
    }
}
复制代码

修改BeanAutoAssembleConfigTest,执行测试

public class BeanAutoAssembleConfitTest {
    @Test
    public void isSameBean(){
        ApplicationContext context = new AnnotationConfigApplicationContext(BeanAutoAssembleConfig.class);
        System.out.println("IoC容器初始化完成");
        Address address = context.getBean("address",Address.class);
        System.out.println(address);
        User user = context.getBean("user", User.class);
        System.out.println(user.getAddress());
        // 关闭容器
        ((AnnotationConfigApplicationContext)context).close();
    }
}
复制代码

执行测试,控制台打印,Address可以成功注入到User中

网络异常,图片无法展示
|

@Autowire在有参数的构造方法上新增加一个只包含Address参数的User构造方法,在方法上面增加@Autowire注解,同时将Setter方法的@Autowire注解注释

@Component
public class User {
    private String username;
    private String password;
    private Address address;
    public User() {
        System.out.println("User 无参数构造方法被调用");
    }
    @Autowired
    public User(Address address) {
        System.out.println("User有参数构造方法被调用");
        this.address = address;
    }
    public Address getAddress() {
        return address;
    }
    //@Autowired
    public void setAddress(Address address) {
        this.address = address;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + ''' +
                ", password='" + password + ''' +
                ", address=" + address +
                '}';
    }
}
复制代码

其他地方不用修改,执行测试类,控制台打印如下,可以成功装配Bean,并且是通过调用User的Setter方法实现的

image.png

参考@Autowire源码,@Autowire注解可以放在构造方法,setter方法,属性及方法的参数上

image.png

Section 02 - Spring的Aware接口

修改entity包中的Product实体类,实现ApplicationContextAware,BeanNameAware,EmbeddedValueResolverAware接口,并实现接口中的方法

@Component
public class Product implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
    private Integer id;
    private String name;
    private Integer price;
    private ApplicationContext applicationContext;
    @Override
    public void setBeanName(String name) {
        System.out.println("beanName为:" + name);
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("IoC容器为:" + applicationContext);
    }
    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        String result = resolver.resolveStringValue("操作系统为:${os.name}");
        System.out.println(result);
    }
    // 省略getter/setter/toString方法
}
复制代码

在config包中增加一个配置类BeanAwareConfig,使用@ComponentScan将entity包中的类注册到容器中

@Configuration
@ComponentScan(value = {"com.citi.entity"})
public class BeanAwareConfig {
}
复制代码

在test包中增加一个测试类

public class BeanAwareConfigTest {
    @Test
    public void testAware(){
        ApplicationContext context = new AnnotationConfigApplicationContext(BeanAutoAssembleConfig.class);
        System.out.println("IoC容器初始化完成");
        Product product = context.getBean("product", Product.class);
        System.out.println(product);
        // 关闭容器
        ((AnnotationConfigApplicationContext)context).close();
    }
}
复制代码

执行测试,控制台输出如下

image.png

控制台输出了IoC容器,beanName等信息,这些都是Spring 底层组件提供的 ,也就是说如果想要把Spring底层的组件注入到自定义的Bean中,需要实现相应的Aware接口,如ApplicationContextAware可以提供IoC容器,这些Aware类都是相关的Processor的后置处理器来处理。


相关文章
|
1月前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
2月前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
74 2
|
3月前
|
Java Kotlin 索引
学习Spring框架特性及jiar包下载
Spring 5作为最新版本,更新了JDK基线至8,修订了核心框架,增强了反射和接口功能,支持响应式编程及Kotlin语言,引入了函数式Web框架,并提升了测试功能。Spring框架可在其官网下载,包括文档、jar包和XML Schema文档,适用于Java SE和Java EE项目。
47 0
|
3月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
133 2
|
3月前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
97 9
|
3月前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
162 5
|
4月前
|
前端开发 Java 数据库
SpringBoot学习
【10月更文挑战第7天】Spring学习
51 9
|
4月前
|
XML Java 数据格式
Spring学习
【10月更文挑战第6天】Spring学习
36 1
|
4月前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
157 2
|
4月前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
495 1