从零开始造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());
            }
        }
        .....
        }

源码地址


相关文章
|
2月前
|
XML Java 数据格式
SpringBoot入门(8) - 开发中还有哪些常用注解
SpringBoot入门(8) - 开发中还有哪些常用注解
58 0
|
12天前
|
Java Spring
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
138 73
|
3月前
|
Java Spring
在使用Spring的`@Value`注解注入属性值时,有一些特殊字符需要注意
【10月更文挑战第9天】在使用Spring的`@Value`注解注入属性值时,需注意一些特殊字符的正确处理方法,包括空格、引号、反斜杠、新行、制表符、逗号、大括号、$、百分号及其他特殊字符。通过适当包裹或转义,确保这些字符能被正确解析和注入。
189 3
|
7天前
|
Java Spring 容器
【SpringFramework】Spring IoC-基于注解的实现
本文主要记录基于Spring注解实现IoC容器和DI相关知识。
40 21
|
12天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
12天前
|
Java Spring
【Spring配置】idea编码格式导致注解汉字无法保存
问题一:对于同一个项目,我们在使用idea的过程中,使用汉字注解完后,再打开该项目,汉字变成乱码问题二:本来a项目中,汉字注解调试好了,没有乱码了,但是创建出来的新的项目,写的注解又成乱码了。
|
2月前
|
XML JSON Java
SpringBoot必须掌握的常用注解!
SpringBoot必须掌握的常用注解!
82 4
SpringBoot必须掌握的常用注解!
|
2月前
|
前端开发 Java Spring
Spring MVC核心:深入理解@RequestMapping注解
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的核心,它将HTTP请求映射到控制器的处理方法上。本文将深入探讨`@RequestMapping`注解的各个方面,包括其注解的使用方法、如何与Spring MVC的其他组件协同工作,以及在实际开发中的应用案例。
48 4
|
2月前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
149 2
|
2月前
|
前端开发 Java Spring
探索Spring MVC:@Controller注解的全面解析
在Spring MVC框架中,`@Controller`注解是构建Web应用程序的基石之一。它不仅简化了控制器的定义,还提供了一种优雅的方式来处理HTTP请求。本文将全面解析`@Controller`注解,包括其定义、用法、以及在Spring MVC中的作用。
61 2