0
点赞
收藏
分享

微信扫一扫

@Autowired注解 -【Spring底层原理

Python芸芸 2022-04-17 阅读 88

【2】自动装配

Spring利用依赖注入(DI)完成对IOC容器中各个组件的依赖关系赋值

@Autowired自动注入(Spring提供的):

  • 默认优先按照去容器中找对应的组件:applicationContext.getBean()

  • 如果找到多个相同类型的组件,再将属性的名称作为组件的ID去容器中查找

  • @Qualifier()注解:该注解指定需要装配的组件ID,而不是使用属性名

  • 自动装配默认必须要对属性赋值,没有就会报错,可以使用@Autowired(required = false)指定非必须就不会报错

  • @Primary注解:自动装配时当出现多个bean候选者时,被注解为@Primary的bean将作为首选者,否则将抛出异常,如果使用了@Qualifier()指定装配的bean,则还是使用明确指定装配的bean

@Resource(JSR250)和@Inject(JSR330)(JDK提供的)

@Resource:

  • 默认按照组件名称进行装配,也可以指定名称进行装配

  • 当找不到与名称匹配的bean会按类型装配

  • 不支持@Primary@Autowired(required = false)功能

  • 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。

  • 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。

  • 如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。

  • 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。

Java开源项目【ali1024.coding.net/public/P7/Java/git】
@Inject:

  • 需要导入javax.inject的包,和Autowired功能一样,但是没有required=false功能

【3】@Autowired和@Resource注解的区别

  • @Autowired由Spring提供,只按照byType注入;@Resource由J2EE提供,默认按照byName自动注入,当找不到与名称匹配的bean会按类型装配

  • @Autowired默认按类型装配,默认情况下必须要求依赖对象存在,如果要允许null值,可以设置它的required属性为false。如果想使用名称装配可以结合@Qualifier注解进行使用。

  • @Resource,默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行名称查找。如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

二、实例分析

这里只对@Autowired注解标注在属性位置进行实例分析

【1】@Autowired注解

// 启动类

@Test

public void TestMain() {

// 创建IOC容器

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

UserService userService = applicationContext.getBean(UserService.class);

System.out.println(“userService:” + userService);

}

// Service

@Service

public class UserService {

@Autowired(required = false) // 指定非必须

@Qualifier(“userDao2”) // 指定装配bean

private UserDao userDao;

@Override

public String toString() {

return “UserService{” +

“userDao=” + userDao +

‘}’;

}

}

// Dao

@Repository

public class UserDao {

private String label = “1”;

public void setLabel(String label) {
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》开源
this.label = label;

}

@Override

public String toString() {

return “UserDao{” +

“label=’” + label + ‘’’ +

‘}’;

}

}

// 配置类

@Configuration

@ComponentScan({“dao”,“service”,“controller”})

public class AppConfig {

@Primary // 首选装配bean

@Bean(“userDao2”)

public UserDao userDao(){

UserDao userDao = new UserDao();

userDao.setLabel(“2”);

return userDao;

}

}

输出结果如下,由于上面使用@Qualifier("userDao2")指定了要装配的bean,所以这里输出的是label=’2‘:

image-20210313102341875

【2】@Resource注解

@Service

public class UserService {

@Resource(name = “userDao2”,type = UserDao.class)

private UserDao userDao;

@Override

public String toString() {

return “UserService{” +

“userDao=” + userDao +

‘}’;

}

}

三、源码追踪

这里对@Autowired注解底层进行源码分析

参考:[https://blog.csdn.net/topdeveloperr/article/details/87971446](()

@Autowired是用来装配bean的,肯定和bean的实例化有关,先经过了refresh方法,在finishBeanFactoryInitialization方法中getBean,然后走getObject的时候触发bean的初始化。bean的初始化是一个很复杂地方,在AbstractAutowireCapableBeanFactory#doCreateBean方法中,先创建一个BeanWrapper,它的内部成员变量wrappedObject中存放的就是实例化的MyService对象,[Spring Bean的生命周期源码详解 - 【Spring底层原理】]((),再往后进入populateBean方法进行属性注入

Spring对autowire注解的实现逻辑位于类:AutowiredAnnotationBeanPostProcessor#postProcessProperties之中,——>findAutowiringMetadata——>buildAutowiringMetadata,核心代码就在buildAutowiringMetadata方法里面

private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {

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

return InjectionMetadata.EMPTY;

} else {

List elements = new ArrayList();

// 需要处理的目标类

Class targetClass = clazz;

do {

List currElements = new ArrayList();

// 通过反射获取该类所有的字段,并遍历每一个字段,并通过方法findAutowiredAnnotation遍历每一个字段的所用注解,并如果用autowired修饰了,则返回auotowired相关属性

ReflectionUtils.doWithLocalFields(targetClass, (field) -> {

MergedAnnotation<?> ann = this.findAutowiredAnnotation(field);

if (ann != null) {

// 校验autowired注解是否用在了static方法上

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

if (this.logger.isInfoEnabled()) {

this.logger.info("Autowired annotation is not supported on static fields: " + field);

}

return;

}

// 判断是否指定了required

boolean required = this.determineRequiredStatus(ann);

currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement(field, required));

最后

做任何事情都要用心,要非常关注细节。看起来不起眼的、繁琐的工作做透了会有意想不到的价值。
当然要想成为一个技术大牛也需要一定的思想格局,思想决定未来你要往哪个方向去走, 建议多看一些人生规划方面的书籍,多学习名人的思想格局,未来你的路会走的更远。

更多的技术点思维导图我已经做了一个整理,涵盖了当下互联网最流行99%的技术点,在这里我将这份导图分享出来,以及为金九银十准备的一整套面试体系,上到集合,下到分布式微服务

到的价值。
当然要想成为一个技术大牛也需要一定的思想格局,思想决定未来你要往哪个方向去走, 建议多看一些人生规划方面的书籍,多学习名人的思想格局,未来你的路会走的更远。

更多的技术点思维导图我已经做了一个整理,涵盖了当下互联网最流行99%的技术点,在这里我将这份导图分享出来,以及为金九银十准备的一整套面试体系,上到集合,下到分布式微服务

[外链图片转存中…(img-uuBTB9iB-1650169398967)]

[外链图片转存中…(img-SF291f5P-1650169398968)]

[外链图片转存中…(img-iDlLf7Wd-1650169398969)]

[外链图片转存中…(img-ullDyu1S-1650169398970)]

举报

相关推荐

0 条评论