Java 基础之Autowired 是否是自动注入
相信很多人对Autowired 注解理解不深入,或者是认为此注解就是spring的自动注入。相信看完本篇文章,你会有更加不一样的理解。
首先我们先看下什么是手动注入?在我们的spring应用程序中,定义多个类,其中某些类依赖某些类,xml中要描述类与类之间的依赖关系,这种由程序员定义,并且描述好依赖关系的用法,我们称之为手动注入。我们看个例子:
package com.shadow.data;
public class X {
private Y y;
public void setY(Y y) {
System.out.println("hello set method ...");
this.y = y;
}
}
package com.shadow.data;
public class Y {
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="x" class="com.shadow.data.X">
<property name="y" ref="y"></property>
</bean>
<bean id="y" class="com.shadow.data.Y"></bean>
</beans>
上面我们定义了两个类,X 依赖于 Y 类,并且我们在xml 中定义了他们的依赖关系,当我们启动spring 应用程序时候,会发现有如下打印:
hello set method ...
Process finished with exit code 0
DI(依赖注入)一共有两种主要的方式,分别是基于构造方法的依赖注入和基于setter方法的依赖注入,不管是手动装配还是自动装配都是基于这两种方式来的。@Autowired这种注入方式是上述setter方式的变体,基于反射技术,实现属性注入。
此处,需要注意的是,如果去掉X中的Y属性,打印是相同的。
spring官网有说明自动装配有四种模型分表是no、bytype、byname、constructor。由于Autowired注解首先根据类型注入,所以容易让程序员认为Autowired注解也是自动注入。其实他们不是一回事。
先给出结论,此处借用大神的一段话:依赖注入是一个过程,主要通过setter和构造方法以及一些变体的方式完成把对象依赖、或者填充上的这个过程叫做依赖注入,不管手动装配还是自动装配都有这个过程;而自动装配模型是一种完成自动装配依赖的手段体现,每一种模型都使用了不同的技术去查找和填充bean;而从spring官网上面可以看到spring只提出了4中自动装配模型(严格意义上是三种、因为第一种是no,表示不使用自动装配、使用),这四个模型分别用一个整形来表示,存在spring的beanDefinition当中,任何一个类默认是no这个装配模型,也就是一个被注解的类默认的装配模型是no也就是手动装配;其中no用0来表示;bytype用2来表示;如果某个类X,假设X的bean对应的beanDefinition当中的autowireMode=2则表示这个类X的自动装配模型为bytype;如果autowireMode=1则表示为byname装配模型。
上面代码基础上增加一个类如下:
package com.shadow.data;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
GenericBeanDefinition x = (GenericBeanDefinition)configurableListableBeanFactory.getBeanDefinition("x");
System.out.println(x.getAutowireMode());
}
}
可以看到打印如下:
...
2
hello set method ...
Process finished with exit code 0
如果将xml去掉,每个类上面加Component注解,如下:
@Configuration
@ComponentScan(basePackages = "com.shadow.data")
public class Main {
public static void main(String[] args) {
System.out.println("...");
// ClassPathXmlApplicationContext classPathXmlApplicationContext =
// new ClassPathXmlApplicationContext("application.xml");
AnnotationConfigApplicationContext annotationConfigApplicationContext=
new AnnotationConfigApplicationContext(Main.class);
}
}
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
GenericBeanDefinition x = (GenericBeanDefinition)configurableListableBeanFactory.getBeanDefinition("x");
System.out.println(x.getAutowireMode());
}
}
@Component
public class X {
@Autowired
private Y y;
public void setY(Y y) {
System.out.println("hello set method ...");
this.y = y;
}
}
@Component
public class Y {
}
...
0
Process finished with exit code 0
打印结果如上所示,可以证明Autowired的bean definition中自动注入模型为0,不属于自动注入。