从零开始造Spring06---实现spring注解-2

简介: 接上一篇《从零开始造Spring05—实现spring注解-1》,今天我们接着学习spring注解。这是学习刘欣老师《从零开始造Spring》课程的学习笔记。上一篇我们实现了Bean的生成,这一篇我们将接着来实现Bean的注入,也叫依赖注入。

前言

接上一篇《从零开始造Spring05—实现spring注解-1》,今天我们接着学习spring注解。这是学习刘欣老师《从零开始造Spring》课程的学习笔记。上一篇我们实现了Bean的生成,这一篇我们将接着来实现Bean的注入,也叫依赖注入。

bb61fb9ff5e221d7e0e05bfea3971640_70.png

具体实现

数据结构

ea959a0c282e9091cc416b5c6785b61f_70.png注: @Autowired 应用的地方有多处,此处我们只实现了应用于Field上。Member对象来自于java.lang.reflect 包,其相当于Field,Method,Constructor的子类。

关键代码

InjectionMetadata类

public class InjectionMetadata {
    private final Class<?> targetClass;
    private List<InjectionElement> injectionElementList;
    public InjectionMetadata(Class<?> targetClass, List<InjectionElement> injectionElementList) {
        this.targetClass = targetClass;
        this.injectionElementList = injectionElementList;
    }
    public List<InjectionElement> getInjectionElementList() {
        return injectionElementList;
    }
       /**
     * 核心的inject,在Bean生命周期的postProcessPropertyValues方法中被调用
     * @param target
     */
    public void inject(Object target) {
        if (injectionElementList == null || injectionElementList.isEmpty()) {
            return;
        }
        for (InjectionElement ele : injectionElementList) {
            ele.inject(target);
        }
    }
}

AutowiredFieldElement 类


public class AutowiredFieldElement extends InjectionElement {
    boolean required;
    public AutowiredFieldElement(Field f, boolean required, AutowireCapableBeanFactory factory) {
        super(f,factory);
        this.required = required;
    }
    public Field getField() {
        return (Field) this.member;
    }
     @Override
    public void inject(Object target) {
        Field field = this.getField();
        try {
            DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
            //获取Bean的实例
            Object value = factory.resolveDependency(desc);
            if (value != null) {
                //将field 置于可访问的
                ReflectionUtils.makeAccessible(field);
                // 将被依赖的Bean注入到依赖的Bean中
                field.set(target, value);
            }
        } catch (Throwable ex) {
            throw new BeanCreationException("Could not autowire field: " + field, ex);
        }
    }
}

DependencyDescriptor 类是用来描述依赖的。相关类图如下:

9acbaf3e14da8f6f7ccbf8631386f9a0_70.png

这里扩展AutowireCapableBeanFactory 新接口主要是为了将resolveDependency方法隐藏于Spring内部,因为BeanFactory 主要是面向使用Spring的程序员。resolveDependency方法于他们没有实际用途。

关键代码:DefaultBeanFactory 类

@Override
    public Object resolveDependency(DependencyDescriptor descriptor) {
        Class<?> typeToMatch = descriptor.getDepencyType();
        for (BeanDefinition bd : this.beanDefinitionMap.values()) {
            //确保BeanDefinition 有class对象
            resolveBeanClass(bd);
            Class<?> beanClass = bd.getBeanClass();
            if (typeToMatch.isAssignableFrom(beanClass)) {
               return getBean(bd.getID());
            }
        }
        return null;
    }
    public void resolveBeanClass(BeanDefinition bd) {
        if (bd.hasBeanClass()) {
            return;
        } else {
            try {
                bd.resolveBeanClass(this.getBeanClassLoader());
            } catch (ClassNotFoundException e) {
                throw new RuntimeException("can't load class:"+bd.getBeanClassName());
            }
        }
    }

Bean的生命周期

Bean的生命周期共有四个阶段:

be632940c5d675a6cec6ecfd3778d5b2_70.png

在此处我们只关注Bean的实例化和初始化阶段。

774ff345af63dcc5759213398698e197_70.png

关键代码:AutowiredAnnotationProcessor 类


@Override
    public void postProcessPropertyValues(Object bean, String beanName) throws BeansException {
        InjectionMetadata metadata = buildAutowiringMetadata(bean.getClass());
        try {
            metadata.inject(bean);
        } catch (Exception ex) {
            throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
        }
    }
    public InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
        LinkedList<InjectionElement> elements = new LinkedList<InjectionElement>();
        Class<?> targetClass = clazz;
        LinkedList<InjectionElement> currentElements = new LinkedList<InjectionElement>();
        for (Field field : targetClass.getDeclaredFields()) {
            Annotation ann = findAutowiredAnnotation(field);
            if (ann != null) {
                if (Modifier.isStatic(field.getModifiers())) {
                    continue;
                }
                boolean required = determineRequiredStatus(ann);
                currentElements.add(new AutowiredFieldElement(field, required, beanFactory));
            }
        }
        for (Method method : targetClass.getDeclaredMethods()) {
            //TODO 处理方法注入
        }
        elements.addAll(0, currentElements);
        targetClass = targetClass.getSuperclass();
        while (targetClass != null && targetClass != Object.class) ;
        return new InjectionMetadata(clazz, elements);
    }


那么怎么使用这些PostProcessor呢?

1. 创建PostProcessor


public AbstractApplicationContext(String configFile) {
        factory = new DefaultBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
        Resource resource = getResourceByPath(configFile);
        reader.loadBeanDefinitions(resource);
        factory.setBeanClassLoader(this.getBeanClassLoader());
        registerBeanPostProcessors(factory);
    }
 protected void registerBeanPostProcessors(ConfigurableBeanFactory beanFactory) {
        AutowiredAnnotationProcessor postProcessor = new AutowiredAnnotationProcessor();
        postProcessor.setBeanFactory(beanFactory);
        beanFactory.addBeanPostProcessor(postProcessor);
    }

1.加到BeanFactory

在ConfigurableBeanFactory上加入


2.在DefaultBeanFactory. populateBean()调用

DefaultBeanFactory 类实现了ConfigurableBeanFactory 接口

protected void populateBean(BeanDefinition bd, Object bean) {
        for (BeanPostProcessor processor : this.getBeanPostProcessors()) {
            if (processor instanceof InstantiationAwareBeanPostProcessor) {
                ((InstantiationAwareBeanPostProcessor)processor).postProcessPropertyValues(bean, bd.getID());
            }
        }
        .....
        }

源码地址


相关文章
|
19天前
|
Java API 数据安全/隐私保护
掌握Spring Boot中的@Validated注解
【4月更文挑战第23天】在 Spring Boot 开发中,@Validated 注解是用于开启和利用 Spring 的验证框架的一种方式,特别是在处理控制层的输入验证时。本篇技术博客将详细介绍 @Validated 注解的概念和使用方法,并通过实际的应用示例来展示如何在项目中实现有效的数据验证
26 3
|
20天前
|
前端开发 Java 开发者
深入理解Spring Boot中的@Service注解
【4月更文挑战第22天】在 Spring Boot 应用开发中,@Service 注解扮演着特定的角色,主要用于标识服务层组件。本篇技术博客将全面探讨 @Service 注解的概念,并提供实际的应用示例,帮助开发者理解如何有效地使用这一注解来优化应用的服务层架构
76 1
|
20天前
|
Java 开发者 Spring
深入理解Spring Boot的@ComponentScan注解
【4月更文挑战第22天】在构建 Spring Boot 应用时,@ComponentScan 是一个不可或缺的工具,它使得组件发现变得自动化和高效。这篇博客将详细介绍 @ComponentScan 的基本概念、关键属性及其在实际开发中的应用。
30 4
|
21天前
|
Java 开发者 Spring
深入理解 Spring Boot 中的 @EnableAutoConfiguration 注解:概念与实践
【4月更文挑战第21天】在 Spring Boot 项目中,@EnableAutoConfiguration 注解是实现自动配置的核心,它可以根据项目的依赖和配置,自动地配置 Spring 应用程序中的 Bean
33 3
|
22天前
|
Java API 网络架构
深入理解 Spring Boot 中的 @RestController 注解:概念与实践
【4月更文挑战第20天】在现代Web开发中,创建RESTful服务已成为常态。Spring Boot通过提供@RestController注解,极大简化了REST API的开发过程。本篇博客旨在详细介绍@RestController的概念、优势以及在Spring Boot项目中的具体应用方法。
32 8
|
22天前
|
Java 开发者 Spring
Spring Framework 中的 @Autowired 注解:概念与使用方法
【4月更文挑战第20天】在Spring Framework中,@Autowired 注解是实现依赖注入(Dependency Injection, DI)的一种非常强大的工具。通过使用 @Autowired,开发者可以减少代码中的引用绑定,提高模块间的解耦能力
33 6
|
22天前
|
XML Java 数据库
探索 Spring Boot 中的 @Configuration 注解:核心概念与应用
【4月更文挑战第20天】在 Spring Boot 项目中,@Configuration 注解扮演了一个关键角色,它标识一个类作为配置源,这些配置用于定义和管理 Spring 应用程序中的 Bean
42 7
|
17天前
|
缓存 Java Sentinel
Springboot 中使用 Redisson+AOP+自定义注解 实现访问限流与黑名单拦截
Springboot 中使用 Redisson+AOP+自定义注解 实现访问限流与黑名单拦截
|
6天前
|
运维 Java 程序员
Spring5深入浅出篇:基于注解实现的AOP
# Spring5 AOP 深入理解:注解实现 本文介绍了基于注解的AOP编程步骤,包括原始对象、额外功能、切点和组装切面。步骤1-3旨在构建切面,与传统AOP相似。示例代码展示了如何使用`@Around`定义切面和执行逻辑。配置中,通过`@Aspect`和`@Around`注解定义切点,并在Spring配置中启用AOP自动代理。 进一步讨论了切点复用,避免重复代码以提高代码维护性。通过`@Pointcut`定义通用切点表达式,然后在多个通知中引用。此外,解释了AOP底层实现的两种动态代理方式:JDK动态代理和Cglib字节码增强,默认使用JDK,可通过配置切换到Cglib
|
2天前
|
JSON 前端开发 Java
【JAVA进阶篇教学】第七篇:Spring中常用注解
【JAVA进阶篇教学】第七篇:Spring中常用注解