如何实现一个简易版的 Spring - 如何实现 @Autowired 注解 (2)

在上文我们还没实现将一个类转换为 InjectionMetadata 的操作,也就是需要实现这样的一个方法 InjectionMetadata buildAutowiringMetadata(Class<?> clz),实现过程也比较简单,扫描类中声明的属性找到有 @Autowried 注解解析构造出 InjectinMetadata 实例,核心实现代码如下:

/** * @author mghio * @since 2021-03-07 */ public class AutowiredAnnotationProcessor { private final String requiredParameterName = "required"; private boolean requiredParameterValue = true; private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(); public AutowiredAnnotationProcessor() { this.autowiredAnnotationTypes.add(Autowired.class); } public InjectionMetadata buildAutowiringMetadata(Class<?> clz) { LinkedList<InjectionElement> elements = new LinkedList<>(); Class<?> targetClass = clz; do { LinkedList<InjectionElement> currElements = new LinkedList<>(); for (Field field : targetClass.getDeclaredFields()) { Annotation ann = findAutowiredAnnotation(field); if (ann != null) { if (Modifier.isStatic(field.getModifiers())) { continue; } boolean required = determineRequiredStatus(ann); elements.add(new AutowiredFieldElement(field, required, beanFactory)); } } elements.addAll(0, currElements); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return new InjectionMetadata(clz, elements); } protected boolean determineRequiredStatus(Annotation ann) { try { Method method = ReflectionUtils.findMethod(ann.annotationType(), this.requiredParameterName); if (method == null) { return true; } return (this.requiredParameterValue == (Boolean) ReflectionUtils.invokeMethod(method, ann)); } catch (Exception e) { return true; } } private Annotation findAutowiredAnnotation(AccessibleObject ao) { for (Class<? extends Annotation> annotationType : this.autowiredAnnotationTypes) { Annotation ann = AnnotationUtils.getAnnotation(ao, annotationType); if (ann != null) { return ann; } } return null; } ... }

上面在做数据结构抽象时定义好了注入元素的抽象父类 InjectionElement,这里需要定义一个子类表示字段注入类型,命名为 AutowiredFieldElement,依赖 AutowireCapableBeanFactory 接口的能力解析出字段所属类型的 Bean,然后调用属性的 setter 方法完成注入,在基于我们上面定义好的数据结构后实现比较简单,主要代码如下:

/** * @author mghio * @since 2021-03-07 */ public class AutowiredFieldElement extends InjectionElement { private final boolean required; public AutowiredFieldElement(Field field, boolean required, AutowireCapableBeanFactory factory) { super(field, factory); this.required = required; } public Field getField() { return (Field) this.member; } @Override void inject(Object target) { Field field = this.getField(); try { DependencyDescriptor descriptor = new DependencyDescriptor(field, this.required); Object value = factory.resolveDependency(descriptor); if (value != null) { ReflectionUtils.makeAccessible(field); field.set(target, value); } } catch (Throwable e) { throw new BeanCreationException("Could not autowire field:" + field, e); } } } 注入到 Spring 中

接下来面临的问题是:要在什么时候调用上面这些类和方法呢?在这里我们回顾一下 Spring 中 Bean 的生命周期,其中几个钩子入口如下图所示:

bean-lifecycle.png

通过生命周期开放的钩子方法可以看出我们需要在 InstantiationAwareBeanPostProcessor 接口的 postProcessPropertyValues 方法中实现 Autowired 注入,将前面的 AutowiredAnnotationProcessor 类实现该接口然后在 postProcessPropertyValues 方法处理注入即可。这部分的整体类图如下所示:

AutowriedAnnotationProcessor.png

AutowiredAnnotationProcessor 处理器实现的 postProcessPropertyValues() 方法如下:

/** * @author mghio * @since 2021-03-07 */ public class AutowiredAnnotationProcessor implements InstantiationAwareBeanProcessor { ... @Override public void postProcessPropertyValues(Object bean, String beanName) throws BeansException { InjectionMetadata metadata = this.buildAutowiringMetadata(bean.getClass()); try { metadata.inject(bean); } catch (Throwable e) { throw new BeanCreationException(beanName, "Injection of autowired dependencies failed"); } } }

然后只需要在抽象父类 AbstractApplicationContext 构造函数注册那些我们定义的 processor,然后在 Bean 注入的时候(DefaultBeanFactory.populateBean())调用 processor 的 postProcessPropertyValues 方法完成属性注入,抽象类 AbstractApplicationContext 改动部分的代码如下:

/** * @author mghio * @since 2021-03-07 */ public abstract class AbstractApplicationContext implements ApplicationContext { ... public AbstractApplicationContext(String configFilePath) { ... registerBeanPostProcessor(beanFactory); } protected void registerBeanPostProcessor(ConfigurableBeanFactory beanFactory) { AutowiredAnnotationProcessor postProcessor = new AutowiredAnnotationProcessor(); postProcessor.setBeanFactory(beanFactory); beanFactory.addBeanPostProcessor(postProcessor); } ... }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygjjd.html