从源码层面带你实现一个自动注入注解

从源码层面带你实现一个自动注入注解public void inject(Object target, Nullable String beanName, Nullable PropertyValues pvs) throws Throwab

public voidject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {

集合checkedElements=this.checkedElements;

//带注释的方法或属性列表

迭代集合元素=

(checkedElements!=null ?checkedElements : this.injectedElements);

if (!elementsToIterate.isEmpty()) {

for (InjectedElement 元素: elementsToIterate) {

element.inject(目标, beanName, pvs);

}

}

}

循环调用使用先前注释的方法或属性构造的对象AutowiredFieldElement#inject 和AutowiredMethodElement#inject。

/**

构造处理对象的属性上有注释。

*/

私有类AutowiredFieldElement 扩展InjectionMetadata.InjectedElement {

我想要一个私有的最终布尔值。

缓存私有易失性布尔值。

@可为空

私有易失性对象cachedFieldValue;

public AutowiredFieldElement(field 字段,需要布尔值) {

超级(字段,空);

this.required=必需;

}

@覆盖

protected voidject(Object Bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {

//获取属性名称

字段字段=(字段) this.member;

对象的价值。

//如果bean不是单例,则重复注入操作。

if (this.cached) {

尝试{

值=solvedCachedArgument(beanName, this.cachedFieldValue);

}

catch (NoSuchBeanDefinitionException ex) {

//缓存参数的目标bean 被意外删除- 重新解析

值=solveFieldValue(字段, Bean, BeanName);

}

}

除此之外{

//第一次创建时填充这个方法

值=solveFieldValue(字段, Bean, BeanName);

}

如果(值!=null){

//如果该属性不是公共的,则将其设置为可访问的属性

ReflectionUtils.makeAccessible(field);

field.set(Bean, 值);

}

}

@可为空

私有对象replaceFieldValue(字段字段,对象bean,@Nullable String beanName){

//构造DependencyDescriptor对象

依赖描述符描述=新的依赖描述符(field, this.required);

desc.setContainingClass(bean.getClass());

//注入的Bean 数量。 字段可能是一个列表

设置autowiredBeanNames=new LinkedHashSet(1)。

Assert.state(beanFactory !=null, “没有可用的BeanFactory”);

//获取beanFactory类型转换类

TypeConverter typeConverter=beanFactory.getTypeConverter();

对象的价值。

尝试{

//查找依赖项

value=beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);

}

catch (BeansException ex) {

抛出新的UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);

}

已同步(此){

if (!this.cached) {

对象缓存字段值=null;

if (值!=null || this.required) {

缓存字段值=描述;

//填写依赖关系

registerDependentBeans(beanName, autowiredBeanNames);

//判断是否只有一个注入依赖

if (autowiredBeanNames.size()==1) {

String autowiredBeanName=autowiredBeanNames.iterator().next();

if (beanFactory.containsBean(autowiredBeanName)

beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {

queuedFieldValue=新的ShortcutDependencyDescriptor(

desc, autowiredBeanName, field.getType());

}

}

}

this.cachedFieldValue=缓存字段值;

this.cached=true;

}

}

返回值;

}

}

/**

构造处理对象的方法上有注释

*/

私有类AutowiredMethodElement 扩展InjectionMetadata.InjectedElement {

我想要一个私有的最终布尔值。

缓存私有易失性布尔值。

@可为空

私有易失性对象[]缓存方法参数;

public AutowiredMethodElement(方法方法,需要布尔值,@Nullable PropertyDescriptor pd) {

超级(方法,pd);

this.required=必需;

}

@覆盖

protected voidject(Object Bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {

//检查该属性是否之前已插入。如果main值为true,则不会进行二次覆盖。

if (checkPropertySkipping(pvs)) {

返回;

}

方法方法=(方法) this.member;

对象[]参数;

if (this.cached) {

尝试{

参数=solveCachedArguments(beanName);

}

catch (NoSuchBeanDefinitionException ex) {

//缓存参数的目标bean 被意外删除- 重新解析

参数=solveMethodArguments(方法, Bean, BeanName);

}

}

除此之外{

//第一次创建时填充这个方法

参数=solveMethodArguments(方法, Bean, BeanName);

}

if(参数!=null){

尝试{

//如果该属性不是公共的,则将其设置为可访问的属性

ReflectionUtils.makeAccessible(方法);

//调用方法并传递参数

method.invoke(Bean, 参数);

}

catch (InvokingTargetException ex) {

抛出ex.getTargetException()。

}

}

}

@可为空

私有对象[]solveCachedArguments(@Nullable String beanName) {

Object[] 缓存方法参数=this.cachedMethodArguments;

if (cachedMethodArguments==null) {

返回空值。

}

Object[] 参数=new Object[cachedMethodArguments.length];

for (int i=0; i argument.length; i++) {

Argument[i]=solvedCachedArgument(beanName, cachedMethodArguments[i]);

}

返回参数。

}

@可为空

private Object[]solveMethodArguments(方法方法,对象bean,@Nullable String beanName) {

//get方法有一些参数

int argumentCount=method.getParameterCount();

对象[]参数=新对象[参数计数];

依赖描述符[]描述符=新的依赖描述符[参数计数];

设置autowiredBeans=new LinkedHashSet(argumentCount);

Assert.state(beanFactory !=null, “没有可用的BeanFactory”);

TypeConverter typeConverter=beanFactory.getTypeConverter();

for (int i=0; i argument.length; i++) {

//方法参数。通过从方法参数获取i 来构造MethodParameter 对象。

MethodParameter methodParam=new MethodParameter(方法, i);

依赖描述符currDesc=new 依赖描述符(methodParam, this.required);

currDesc.setContainingClass(bean.getClass());

描述符[i]=currDesc;

尝试{

//获取方法中i参数的内容

对象arg=beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);

if (arg==null !this.required) {

参数=空;

休息;

}

参数[i]=参数;

}

catch (BeansException ex) {

抛出新的UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);

}

}

已同步(此){

if (!this.cached) {

if(参数!=null){

依赖描述符[]缓存方法参数=Arrays.copyOf(descriptor, argument.length);

registerDependentBeans(beanName, autowiredBeans);

if (autowiredBeans.size()==argumentCount) {

迭代器it=autowiredBeans.iterator();

类?[] paramTypes=method.getParameterTypes();

for (int i=0; i paramTypes.length; i++) {

String autowiredBeanName=it.next();

if (beanFactory.containsBean(autowiredBeanName)

beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {

queuedMethodArguments[i]=new ShortcutDependencyDescriptor(

描述符[i],autowiredBeanName,paramTypes[i]);

}

}

}

this.cachedMethodArguments=缓存方法参数;

}

除此之外{

this.cachedMethodArguments=null;

}

this.cached=true;

}

}

返回参数。

}

}

以上就是@Autowired实现的完整流程。 可以概括如下。

PopulateBean-AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues

– 获取带注释的属性和方法来构造AutowiredFieldElement 和AutowiredMethodElement 对象,并在循环中调用注入以进行属性调用。

自动插入自定义注释。

编写抽象类代码。

com.yunlongn.common.core.autowired 包;

导入org.apache.commons.logging.Log。

导入org.apache.commons.logging.LogFactory。

导入org.springframework.beans.BeansException。

导入org.springframework.beans.PropertyValues。

导入org.springframework.beans.factory.*。

导入org.springframework.beans.factory.annotation.InjectionMetadata。

导入org.springframework.beans.factory.config.ConfigurableListableBeanFactory。

导入org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor。

导入org.springframework.core.annotation.AnnotationUtils。

导入org.springframework.core.annotation.MergedAnnotation。

导入org.springframework.core.annotation.MergedAnnotations。

导入org.springframework.lang.Nullable。

导入org.springframework.util.ReflectionUtils。

导入org.springframework.util.StringUtils。

导入java.beans.PropertyDescriptor。

导入java.lang.annotation.Annotation;

导入java.lang.reflect.*;

导入java.util.*。

导入java.util.concurrent.ConcurrentHashMap;

/**

摘要自动注入方法

@作者云鲁贡

*/

公共抽象类AbstractAnnotationBeanPostProcessor 实现InstantiationAwareBeanPostProcessor {;

私有最终SetClass?扩展注释annotationTypes=new LinkedHashSet(4);

私有最终MapString,InjectionMetadataInjectionMetadataCache=new ConcurrentHashMap(256);

protected Final Log Logger=LogFactory.getLog(getClass());

/**

待处理的annotationType对象

@return注解自定义注解

*/

公共抽象类是否扩展注释annotationType()?

AbstractAnnotationBeanPostProcessor () {

类扩展注释annotation=this.annotationType();

注释类型.add(注释);

}

@覆盖

公共对象postProcessBeforeInstantiation(Class? beanClass, String beanName) 抛出BeansException {

返回InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);

}

@覆盖

public boolean postProcessAfterInstantiation(Object Bean, String beanName) throws BeansException {

返回InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);

}

@覆盖

公共PropertyValues postProcessProperties(PropertyValues pvs,对象Bean,字符串beanName){

InjectionMetadata 元数据=findAbstractMetadata(beanName, bean.getClass(), pvs);

尝试{

//注入数据

元数据.注入(bean, beanName, pvs);

}

catch (BeanCreationException ex) {

扔掉原件。

}

catch(抛出的例子){

throw new BeanCreationException(beanName, “自动连线依赖注入失败”, ex);

}

返回pv。

}

private InjectionMetadata findAbstractMetadata(String beanName, Class?clazz, @Nullable PropertyValues pvs) {

String queueKey=(StringUtils.hasLength(beanName) ? beanName : clazz.getName());

InjectionMetadata 元数据=this.injectionMetadataCache.get(cacheKey);

//获取该类的InjectionMetadata是否已读取,如果已读取,则直接从缓存中检索。

if (InjectionMetadata.needsRefresh(元数据, clazz)) {

已同步(this.injectionMetadataCache){

//再检查一遍

元数据=this.injectionMetadataCache.get(cacheKey);

if (InjectionMetadata.needsRefresh(元数据, clazz)) {

if(元数据!=null){

元数据.clear(pvs);

}

元数据=buildAbstractMetadata(clazz);

this.injectionMetadataCache.put(cacheKey, 元数据);

}

}

}

返回元数据。

}

私有InjectionMetadata buildAbstractMetadata(final Class? clazz) {

if (!AnnotationUtils.isCandidateClass(clazz, this.annotationTypes)) {

返回InjectionMetadata.EMPTY。

}

ListInjectionMetadata.InjectedElement 元素=new ArrayList();

类?目标类=clazz;

做{

最终ListInjectionMetadata.InjectedElement currElements=new ArrayList();

//循环遍历targetClass的所有字段,执行FieldCallback逻辑(函数式编程接口,传递执行函数)

ReflectionUtils.doWithLocalFields(targetClass, 字段- {

//获取字段的Annotation注解

合并注释?

if (ann !=null) {

//判断是否为静态属性。如果是静态属性,则不会执行注入。

if (Modifier.isStatic(field.getModifiers())) {

如果(logger.isInfoEnabled()) {

logger.info(\’静态字段不支持抽象注释: \’ + field);

}

返回;

}

currElements.add(new AbstractFieldElement(field, ann));

}

});

//数据添加到数组的开头,父类的注解放在开头。

elements.addAll(0, currElements);

targetClass=targetClass.getSuperclass();

}

while (targetClass !=null targetClass !=Object.class);

返回InjectionMetadata.forElements(elements, clazz);

}

@可为空

私有MergedAnnotation? findAbstractAnnotation(AccessibleObject ao){

//将指定方法的注解合并为一个注解

MergedAnnotations 注释=MergedAnnotations.from(ao);

//循环遍历要扫描的注释。第一个注释类型被识别。

for (class? 注解类型: 扩展this.annotationTypes) {

合并注释?

if (annotation.isPresent()) {

返回注释。

}

}

返回空值。

}

@不建议

@覆盖

公共PropertyValues postProcessPropertyValues(

PropertyValues pvs, PropertyDescriptor[] pds, 对象bean, 字符串beanName) {

返回postProcessProperties(pvs, bean, beanName);

}

@覆盖

公共对象postProcessBeforeInitialization(对象Bean,字符串beanName) 抛出BeansException {

返回InstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);

}

@覆盖

公共对象postProcessAfterInitialization(Object Bean, String beanName) 抛出BeansException {

返回InstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);

}

最后

我们将分享一些结构化面试问题,您可以使用它们来审查和准备加薪面试。

以下是这些面试问题对应的技术点:

JVMMySQLMybatisMongoDBRedisSpringSpring bootSpring CloudKafkaRabbitMQNginx.

主要类别有:

基本Java 数据结构和算法并发编程数据库设计模式微服务消息传递中间件

i) 抛出BeansException {

返回InstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);

}

最后

我们将分享一些结构化面试问题,您可以使用它们来审查和准备加薪面试。

以下是这些面试问题对应的技术点:

JVMMySQLMybatisMongoDBRedisSpringSpring bootSpring CloudKafkaRabbitMQNginx.

主要类别有:

基本Java 数据结构和算法并发编程数据库设计模式微服务消息传递中间件

[外部链接图像正在传输.(img-fZkbWvDL-1719186353764)]

[正在传输外部链接图像.(img-vJPQYiMa-1719186353764)]

[正在传输外部链接图像.(img-EJ31UBka-1719186353765)]

[正在传输外部链接图像.(img-HsFhYQw8-1719186353765)]

[外部链接照片正在传输中.(img-6y7Jrqia-1719186353766)]

[外部链接图像正在传输.(img-lmb9zPuB-1719186353766)]

[外部链接图片正在传输中.(img-Xdzv2g6y-1719186353766)]

[外部链接图像正在传输.(img-AmGvA6JH-1719186353767)]

[正在传输外部链接图像.(img-wNpbgPtb-1719186353767)]

# 以上从源码层面帮助实现自动插入注释的相关内容来源网,仅供参考。相关信息请参见官方公告。

原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/91898.html

(0)
CSDN's avatarCSDN
上一篇 2024年6月24日 上午7:38
下一篇 2024年6月24日 上午8:14

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注