spring-ioc-自动装配

本篇博客主要为spring专栏的spring-ioc 核心之springbean的装配错误纠正
https://blog.csdn.net/qq_38108719/article/details/99674379

纠正如下

@Autowired和@Resource不属于自动装配模型中的任意一种。本篇博客会有所涉及,后期会有源码验证

有兴趣的朋友可以看一下spring的内置处理器其中的有两个是专门解析@Autowired和@Resource这两个注解的。
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor

首先根据spring官网提到的spring框架中inversion of control的注入方式只有setter 方法 和 构造方法

再看看提到的注入模型(4种)

那么这四种我们是如何使用的呢,spring 1.0版本所提供的xml形式配置的,为该文件中所有的bean如下

或者为单个bean如下

扫描二维码关注公众号,回复: 12977287 查看本文章

那我们可以知道一点的就是只有xml的配置方式才能使用自动装配模型

那么为什么@Autowired和@Resource不是呢。
我们在网上找@Autowired和@Resource的区别的时候,会提到@Autowired是先bytype再byname(set方法名字)

而@Resource是先byname再bytype,找不到就会报错。

那么我们现在就往下看到底是根据装配模型的byname 和 bytype,还是根据一种技术通过name 和 type 方式进行查找呢。

首先我们知道spring框架提供的这些注解是在spring2.5以后更新的

而spring官网中也并没有提到这两个注解使用了自动装配模型中的任意一点,如图我们可以进去看

https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-autowired-annotation

我们现在用代码来解释的问题是@Autowired和@Resource这两个注解并没有使用到自动注入模型中的任意一种

环境一 spring传统的xml形式,来测试自动注入模型中的一种bytype

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		" default-autowire="byType">
		<context:component-scan base-package="org.springframework.work2"></context:component-scan>
		<bean id="uService" class="org.springframework.work2.service.UService" >

		</bean>

		<bean id="tService" class="org.springframework.work2.service.TService">

		</bean>
</beans>



public class TService{
	
	UService uService;

	public UService getUService() {
		return this.uService;
	}

	public void setUService(UService uService) {
		this.uService = uService;
	}

}

public class UService {
}

public class Main {

	public static void main(String[] args) {
		//AnnotationConfigApplicationContext cxc = new AnnotationConfigApplicationContext(AppConfig.class);
		ClassPathXmlApplicationContext cxc = new ClassPathXmlApplicationContext("classpath:spring2.xml");
		TService tService = (TService) cxc.getBean("tService");
		System.out.println(tService.getUService());

	}
}

我们需要的不是打印结果,毫无疑问是能正常注入的。我们点进源码中看,调用链为

org.springframework.context.support.AbstractApplicationContext#refresh

org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization

org.springframework.beans.factory.config.ConfigurableListableBeanFactory#preInstantiateSingletons

org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

org.springframework.beans.factory.support.AbstractBeanFactory#createBean

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

我们先设置好断点再重新断点点进来

我们通过后置处理器来看一看这个bean的注入模型是什么


而我们刚好在xml配置自动装配模型就是bytype。

我们现在看第二种环境 测试注解@Autowired和@Resource

环境二 使用注解的形式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		">
		<context:component-scan base-package="org.springframework.work2"></context:component-scan>
		<bean id="uService" class="org.springframework.work2.service.UService" >

		</bean>

		<bean id="tService" class="org.springframework.work2.service.TService">

		</bean>
</beans>

package org.springframework.work2.service;

import org.springframework.stereotype.Component;

public class UService {
}


package org.springframework.work2.service;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

public class TService{

	@Autowired
	UService uService;

	public UService getUService() {
		return this.uService;
	}

	public void setUService(UService uService) {
		this.uService = uService;
	}

}

package org.springframework.work2;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.work2.app.AppConfig;
import org.springframework.work2.service.TService;
import org.springframework.work2.service.UService;

public class Main {

	public static void main(String[] args) {
		//AnnotationConfigApplicationContext cxc = new AnnotationConfigApplicationContext(AppConfig.class);
		ClassPathXmlApplicationContext cxc = new ClassPathXmlApplicationContext("classpath:spring2.xml");
		TService tService = (TService) cxc.getBean("tService");
		System.out.println(tService.getUService());

	}
}

同样的断点同样的调用链,我们只看这两种注解的最后调用方法


我们再来打印看一下这个bean的装配模型

当然这个装配模型我们也可以在这个后置处理器中去手动设置为bytype或者是byname 

beanDefinition.setAutowireMode(0); 0-1-2-3-4...

这边两个处理器就是上面提到过的解析@Autowired和@Resource两个注解的处理器。
很显然没有走bytype或者byname的方法。后面的博客也会证明这两个注解@Autowired和@Resource使用的注入技术是type和name 与 自动注入模型毫无关联。

猜你喜欢

转载自blog.csdn.net/qq_38108719/article/details/103061155
今日推荐