@Autowired自动装配及原理

        使用Autowired装配属性时,当容器在扫描中扫描到@Autowired时,就会在IOC容器中自动的查找到需要的Bean对象(先按照类型进行装配)。当查询结果是一个的时候,就会直接进行装配。当查询的结果有多个的时候,@Autowired会根据名称进行查找(自动切换按照名称(bean对象的Id)进行装配)。

使用方法

1.通过set方法进行类型自动装配,并且set方法可以省略。语法:@Autowired(required="true“)如果IOC容器中没有一个匹配的bean对象。并且制定required属性为true就会抛出NoSuchBeanDefinitionException异常,如果required属性为“false”,就不会抛出这种异常

package com.alibaba.controller;

import com.alibaba.service.IService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import javax.sound.midi.SoundbankResource;


@Controller
public class ControllerImp implements IController {
    @Autowired
    private IService service;
    @Override
    public void add() {
        System.out.println("——->这是controller层的add()方法");
        service.add();
    }
}

package com.alibaba.service;

import com.alibaba.dao.IDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class ServiceImp implements IService{
    @Autowired
    private IDao dao;

    @Override
    public void add() {
        System.out.println("——->这是service层的add()方法");
        dao.add();
    }
}
package com.alibaba.dao;

import org.springframework.stereotype.Repository;


@Repository
public class DaoImp implements IDao{

    @Override
    public void add() {
        System.out.println("——-->这是dao层的add()方法");
    }
}

 如上,设置了三层。在测试类中从Ioc容器中获取ControllerImp对象,调用它的add()方法,会发现三层串联着调用,说明@Autowired已经自动注入了bean对象。

当IOC容器中有多个对象时,@Autowired会自动切换成按照名称进行装配。 

package com.alibaba.dao;

import org.springframework.stereotype.Repository;


@Repository(value = "dao2")
public class DaoImp2 implements IDao {
    @Override
    public void add() {
        System.out.println("--->这是dao2的add方法");
    }
}
package com.alibaba.service;

import com.alibaba.dao.IDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ServiceImp implements IService{
    @Autowired
    private IDao dao2;

    @Override
    public void add() {
        System.out.println("——->这是service层的add()方法");
        dao2.add();
    }
}

 如果容器中有多个对象可以与之匹配,这时会自动切换按照名称装配,但是按照名称却没有与之匹配的对象。这时程序会抛出NoUniqueBeanDefinitionException异常

@Autowired注解的实现过程就是调用了AutowiredAnnotationBeanPostProcessor类中的方法。

核心方法postProcessProperties:

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//1.获取当前类中标注了@Autowired的成员变量和方法的参数封装在metadata对象里
        InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);
 
        try {
//2.利用反射赋值
            metadata.inject(bean, beanName, pvs);
            return pvs;
        } catch (BeanCreationException var6) {
            throw var6;
        } catch (Throwable var7) {
            throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);
        }
    }

 1.调用findAutowiringMetadata方法查询

  private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
        //获取当前bean的名称
        String cacheKey = StringUtils.hasLength(beanName) ? beanName : clazz.getName();
       //在缓存中查找是否有当前类的信息
 InjectionMetadata metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
        if (InjectionMetadata.needsRefresh(metadata, clazz)) {
            synchronized(this.injectionMetadataCache) {
                metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
                if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                    if (metadata != null) {
                        metadata.clear(pvs);
                    }
                //调用此方法解析当前类,获得所有标注@AutoWired的字段 并存入metada中
                    metadata = this.buildAutowiringMetadata(clazz);
                //存入缓存中
                    this.injectionMetadataCache.put(cacheKey, metadata);
                }
            }
        }
        //返回得到@AutoWired的字段的metadata
        return metadata;
    }

2.执行inject方法完成属性注入

 public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        //metadata中的数据放在集合中
        Collection<InjectionMetadata.InjectedElement> checkedElements = this.checkedElements;
 
       Collection<Injectio
nMetadata.InjectedElement> elementsToIterate = checkedElements != null ? checkedElements : this.injectedElements;
 
        if (!((Collection)elementsToIterate).isEmpty()) {
            Iterator var6 = ((Collection)elementsToIterate).iterator();
//遍历集合拿到标注了@AutoWired的成员变量和方法
            while(var6.hasNext()) {
                InjectionMetadata.InjectedElement element = (InjectionMetadata.InjectedElement)var6.next();
//遍历调用内部类的方法完成属性赋值
                element.inject(target, beanName, pvs);
            }
        }
 
    }

inject方法:

protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) throws Throwable {
               //判断是方法还是成员变量
            if (this.isField) {
                //得到bean的Field对象
                Field field = (Field)this.member;
                //底层做了判断然后停止修饰符检查
                ReflectionUtils.makeAccessible(field);
                //利用反射给成员变量赋值 
                field.set(target, this.getResourceToInject(target, requestingBeanName));
            } else {
                if (this.checkPropertySkipping(pvs)) {
                    return;
                }
 
                try {
                //得到bean的方法对象
                    Method method = (Method)this.member;
                    //停止修饰符检查
                    ReflectionUtils.makeAccessible(method);
                    //利用invoke给targe赋值,值为此方法的返回值
                    method.invoke(target, this.getResourceToInject(target, requestingBeanName));
                } catch (InvocationTargetException var5) {
                    throw var5.getTargetException();
                }
            }
 
        }

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
回答: @Autowired是Spring提供的注解,用于实现自动装配。它的原理是通过IOC容器在扫描中扫描到@Autowired注解时,自动查找并装配所需的Bean对象。默认情况下,@Autowired按照类型进行装配,如果查询结果只有一个,就直接进行装配;如果查询结果有多个,@Autowired会根据名称进行查找并装配。\[2\]在启动Spring IOC时,容器会自动装配一个AutowiredAnnotationBeanPostProcessor后置处理器,用于处理@Autowired注解。当容器扫描到@Autowired注解时,后置处理器会在IOC容器中自动查找所需的Bean对象,并进行装配。\[3\]与@Autowired不同,@Resource是JDK提供的注解,也用于实现自动装配。@Resource默认按照名称进行装配,它会根据名称在IOC容器中查找所需的Bean对象进行装配。\[1\]总的来说,@Autowired和@Resource的区别在于注入方式和提供者不同。 #### 引用[.reference_title] - *1* [@Autowired自动装配原理](https://blog.csdn.net/qq_46853052/article/details/127502517)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [@Autowired自动装配原理](https://blog.csdn.net/m0_59340907/article/details/127498517)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [@Autowired自动装配原理](https://blog.csdn.net/weixin_68286174/article/details/125943218)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

磨剑斩秋招

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值