依赖注入的模式和类型
模式
手动模式
配置或者编程的方式:
- XML 资源配置元信息(常用)
- Java 注解配置元信息(常用)
- API 配置元信息
自动模式
实现方提供依赖自动关联的方式,按照内建的注入规则:
Autowiring(自动绑定)类型
Setter 方法:<proeprty name= "user" ref= "userBean" />
构造器:<constructor-arg name="user" ref="userBean" />
字段:@Autowired User user;
方法:@Autowired User user;
接口回调:class MyBean implements BeanFactoryAware { ... }
自动绑定(Autowiring)
官方说明
The Spring container can autowire relationships between collaborating beans. You can let Spring resolve collaborators (other beans) automatically for your bean by inspecting the contents of the ApplicationContext.
Spring 容器可以自动关联依赖 Bean 和被依赖 Bean,可以通过检查 ApplicationContext 的内容来让 Spring 自动解析依赖 Bean 的关系。
优点
Autowiring can significantly reduce the need to specify properties or constructor arguments.
自动绑定可以显著减少指定属性或构造器的需要,比如下述代码:
<bean id="user" class="com.mindartisan.spring.geek.ioc.overview.domain.User"><property name="id" value="1"/><property name="name" value="Steve"/></bean>
如果我将 value="Steve"变成到 ref="myName"这个 Bean,此时 myName 这个 Bean 就会关联到 name 属性上。
如果此时有个名称是 name 的bean,我可以将 <property name="name" value="Steve"/>注释掉,然后再在<bean id="user" class="com.mindartisan.spring.geek.ioc.overview.domain.User"> 添加 autowire="byName,此时 name 这个 Bean 会被自动装配到 name 属性中。
注意:一般显性绑定比较好,如果某 Bean 的属性字段名称变化,此时按名称找的话,找不到(比如 name -> newName,此时没有名称是 newName 的 Bean。
Autowiring can update a configuration as your objects evolve.
随着对象的更新,自动装配可以自动更新配置(这其实是和 Java 语言特性相关,传引用的类型。)
自动绑定(Autowiring)模式
| 模式 | 说明 | 备注 |
|---|---|---|
| no | 默认值,不使用自动绑定,需要手动指定依赖注入对象 | |
| byName | 根据被注入属性的名称作为 Bean 名称进行依赖查找, 并将对象设置到该属性。 | |
| byType | 根据被注入属性的类型作为依赖类型进行查找, 并将对象设置到该属性。 | 有多个相同 type 的 bean 的情况下,可以使用 @Primary注解来设置优先级 |
| constructor | 特殊 byType 类型, 用于构造器参数 |
具体代码,参照 Autowire此枚举:
public enum Autowire {/*** Constant that indicates no autowiring at all.*/NO(AutowireCapableBeanFactory.AUTOWIRE_NO),/*** Constant that indicates autowiring bean properties by name.*/BY_NAME(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME),/*** Constant that indicates autowiring bean properties by type.*/BY_TYPE(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE);private final int value;Autowire(int value) {this.value = value;}public int value() {return this.value;}/*** Return whether this represents an actual autowiring value.* @return whether actual autowiring was specified* (either BY_NAME or BY_TYPE)*/public boolean isAutowire() {return (this == BY_NAME || this == BY_TYPE);}}
具体的可以看 AutowireCapableBeanFactory此类,规定了以下几种:
int AUTOWIRE_NO = 0;int AUTOWIRE_BY_NAME = 1;int AUTOWIRE_BY_TYPE = 2;int AUTOWIRE_CONSTRUCTOR = 3;@Deprecatedint AUTOWIRE_AUTODETECT = 4;
自动绑定(Autowiring)限制和不足
限制不足
官方文档:
- Explicit dependencies in property and constructor-arg settings always override autowiring. You cannot autowire simple properties such as primitives, Strings, and Classes (and arrays of such simple properties). This limitation is by-design.
- Autowiring is less exact than explicit wiring. Although, as noted in the earlier table, Spring is careful to avoid guessing in case of ambiguity that might have unexpected results. The relationships between your Spring-managed objects are no longer documented explicitly.
- Wiring information may not be available to tools that may generate documentation from a Spring container.
Multiple bean definitions within the container may match the type specified by the setter method or constructor argument to be autowired. For arrays, collections, or Map instances, this is not necessarily a problem. However, for dependencies that expect a single value, this ambiguity is not arbitrarily resolved. If no unique bean definition is available, an exception is thrown.
个人理解:
- 更准确的
property和constructor-arg会覆盖掉自动绑定。不能自动绑定一些简单的属性,比如原生类型、String 类型、Class 类型,这是设计上的限制。咱们自动绑定的时候,会去绑定一个 Bean 或者引用对象,原生类型没法声明成一个 Bean。 - 自动装配不如显式绑定准确。Spring 对于可能产生歧义的产生意料之外结果的猜测要尽量避免(这里可以理解为你绑定属性的时候,对应要绑定 bean 名称写错了。比如你要将一个类的 User 的属性绑定为 SuperUser 这个 bean,但是你手误写成了 User 这个 bean)
- 绑定的相关信息没法在工具中提示,比如从 Spring 容器中生成对应的容器(我理解的是不知道容器里有没有想要绑定的 Bean)
- 如果应用上下文中有多个 bean 的定义,byType 的时候不知道绑定哪个,会抛异常。
对应方案
官方文档:- Abandon autowiring in favor of explicit wiring.
- Avoid autowiring for a bean definition by setting its autowire-candidate attributes to false, as described in the next section.
- Designate a single bean definition as the primary candidate by setting the primary attribute of its
element to true. - Implement the more fine-grained control available with annotation-based configuration, as described in Annotation-based Container Configuration.—— Limitations and Disadvantages of Autowiring
个人理解:
- 你可以放弃这种方式
- 把
autowire-candidate改为 false - 有多个相同类型 Bean 的时候,用
@primary注解标注 -
Setter 方法依赖注入
手动方式
XML 资源配置元信息
- Java 注解配置元信息
- API 配置元信息
相关代码:
XmlDependencySetterInjectionDemo.class
/*** 基于 xml 资源的依赖 setter 方法注入示例** @author mindartisan.blog.csdn.net* @date*/public class XmlDependencySetterInjectionDemo {public static void main(String[] args) {DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);String xmlResourcePath = "classpath:/META-INF/dependency-setter-injection.xml";// 加载 XML 资源,解析并生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlResourcePath);// 依赖查找并创建 BeanUserHolder userHolder = defaultListableBeanFactory.getBean(UserHolder.class);System.out.println(userHolder);}}
dependency-setter-injection.xml
<?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"><import resource="classpath:/META-INF/dependency-lookup-context.xml"/><bean class="com.mindartisan.spring.geek.ioc.dependency.injection.UserHolder"><!-- 会关联到 id =1,name = Steve 的 bean --><property name="user" ref="user"/><!-- 同理 --><!--<property name="user" ref="superUser"/>--></bean></beans>
AnnotationDependencySetterInjectionDemo.class
/*** 基于注解的依赖 setter 方法注入示例** @author mindartisan.blog.csdn.net* @date*/public class AnnotationDependencySetterInjectionDemo {public static void main(String[] args) {// 创建 BeanFactory 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 配置类applicationContext.register(AnnotationDependencySetterInjectionDemo.class);// 将 User Bean 初始化,供 userHolder(User user) 使用XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";// 加载 XML 资源,解析并生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlResourcePath);// 启动 Spring 应用上下文applicationContext.refresh();UserHolder userHolder = applicationContext.getBean(UserHolder.class);System.out.println(userHolder);// 关闭 Spring 应用上下文applicationContext.close();}// /**// * 此处采用的构造器方式// *// * @param user 用户// * @return {@link UserHolder}// */@Beanpublic UserHolder userHolder(User user) {return new UserHolder(user);}/*** 此处采用 setter 方式** @param user 用户* @return {@link UserHolder}*/// @Bean// public UserHolder userHolder(User user) {// UserHolder userHolder = new UserHolder();// userHolder.setUser(user);// return userHolder;// }}
dependency-lookup-context.xml
<?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="user" class="com.mindartisan.spring.geek.ioc.overview.domain.User" autowire="byName"><property name="id" value="1"/><property name="name" value="Steve"/></bean><bean id="superUser" class="com.mindartisan.spring.geek.ioc.overview.domain.SuperUser" parent="user"primary="true"><property name="address" value="北京"/></bean><!-- 延迟查找使用 --><bean id="objectFactoryCreatingFactoryBean"class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean"><property name="targetBeanName" value="user"/></bean></beans>
ApiDependencySetterInjectionDemo.class
/*** 基于 API 实现依赖 setter 方法注入示例** @author mindartisan.blog.csdn.net* @date*/public class ApiDependencySetterInjectionDemo {public static void main(String[] args) {// 创建 BeanFactory 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 UserHolder 的 BeanDefinitionBeanDefinition userHolderBeanDefinition = createUserHolderBeanDefinition();applicationContext.registerBeanDefinition("userHolder", userHolderBeanDefinition);// 将 User Bean 初始化XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";// 加载 XML 资源,解析并生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlResourcePath);// 启动 Spring 应用上下文applicationContext.refresh();UserHolder userHolder = applicationContext.getBean(UserHolder.class);System.out.println(userHolder);// 关闭 Spring 应用上下文applicationContext.close();}/*** 为 UserHolder 生成 BeanDefinition** @return {@link BeanDefinition}*/private static BeanDefinition createUserHolderBeanDefinition() {// API 用的就是下述代码BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);// 类似 xml 文件中 「ref=""」beanDefinitionBuilder.addPropertyReference("user", "superUser");AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();return beanDefinition;}}
dependency-lookup-context.xml
<?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="user" class="com.mindartisan.spring.geek.ioc.overview.domain.User" autowire="byName"><property name="id" value="1"/><property name="name" value="Steve"/></bean><bean id="superUser" class="com.mindartisan.spring.geek.ioc.overview.domain.SuperUser" parent="user"primary="true"><property name="address" value="北京"/></bean><!-- 延迟查找使用 --><bean id="objectFactoryCreatingFactoryBean"class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean"><property name="targetBeanName" value="user"/></bean></beans>
自动方式
- byName
- byType
相关代码:
AutoWiringByNameDependencySetterInjectionDemo.class
/*** byName Autowiring 依赖 setter 方法注释示例** @author mindartisan.blog.csdn.net* @date*/public class AutoWiringByNameDependencySetterInjectionDemo {public static void main(String[] args) {DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);String xmlResourcePath = "classpath:/META-INF/autowiring-dependency-setter-injection.xml";// 加载 XML 资源,解析并生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlResourcePath);// 依赖查找并创建 BeanUserHolder userHolder = defaultListableBeanFactory.getBean(UserHolder.class);System.out.println(userHolder);}}
autowiring-dependency-setter-injection.xml
<?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"><import resource="classpath:/META-INF/dependency-lookup-context.xml"/><!-- 如果 autowire = "byType",此时会有两个 type 相同的 bean,但是会关联到 superUser,因为 superUser 设置了 primary--><bean class="com.mindartisan.spring.geek.ioc.dependency.injection.UserHolder" autowire="byName"><!-- 会关联到 id =1,name = Steve 的 bean --><!--<property name="user" ref="user"/>--></bean></beans>
构造器依赖注入
手动方式
- XML 资源配置元信息
- Java 注解配置元信息
- API 配置元信息
相关代码:
XmlDependencyConstructorInjectionDemo.class
/*** 基于 xml 资源的依赖 Constructor 注入示例** @author mindartisan.blog.csdn.net* @date*/public class XmlDependencyConstructorInjectionDemo {public static void main(String[] args) {DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);String xmlResourcePath = "classpath:/META-INF/dependency-constructor-injection.xml";// 加载 XML 资源,解析并生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlResourcePath);// 依赖查找并创建 BeanUserHolder userHolder = defaultListableBeanFactory.getBean(UserHolder.class);System.out.println(userHolder);}}
dependency-constructor-injection.xml
<?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"><import resource="classpath:/META-INF/dependency-lookup-context.xml"/><bean class="com.mindartisan.spring.geek.ioc.dependency.injection.UserHolder"><!-- 会关联到 id =1,name = Steve 的 bean --><constructor-arg name="user" ref="superUser"/></bean></beans>
AnnotationDependencyConstructorInjectionDemo.class
/*** 基于注解的依赖 Constructor 注入示例** @author mindartisan.blog.csdn.net* @date*/public class AnnotationDependencyConstructorInjectionDemo {public static void main(String[] args) {// 创建 BeanFactory 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 配置类applicationContext.register(AnnotationDependencyConstructorInjectionDemo.class);// 将 User Bean 初始化,供 userHolder(User user) 使用XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";// 加载 XML 资源,解析并生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlResourcePath);// 启动 Spring 应用上下文applicationContext.refresh();UserHolder userHolder = applicationContext.getBean(UserHolder.class);System.out.println(userHolder);// 关闭 Spring 应用上下文applicationContext.close();}// /**// * 此处采用的构造器方式// *// * @param user 用户// * @return {@link UserHolder}// */@Beanpublic UserHolder userHolder(User user) {return new UserHolder(user);}/*** 此处采用 setter 方式** @param user 用户* @return {@link UserHolder}*/// @Bean// public UserHolder userHolder(User user) {// UserHolder userHolder = new UserHolder();// userHolder.setUser(user);// return userHolder;// }}
dependency-lookup-context.xml
<?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="user" class="com.mindartisan.spring.geek.ioc.overview.domain.User" autowire="byName"><property name="id" value="1"/><property name="name" value="Steve"/></bean><bean id="superUser" class="com.mindartisan.spring.geek.ioc.overview.domain.SuperUser" parent="user"primary="true"><property name="address" value="北京"/></bean><!-- 延迟查找使用 --><bean id="objectFactoryCreatingFactoryBean"class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean"><property name="targetBeanName" value="user"/></bean></beans>
ApiDependencyConstructorInjectionDemo.class
/*** 基于 API 实现依赖 Constructor 注入示例** @author mindartisan.blog.csdn.net* @date*/public class ApiDependencyConstructorInjectionDemo {public static void main(String[] args) {// 创建 BeanFactory 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 UserHolder 的 BeanDefinitionBeanDefinition userHolderBeanDefinition = createUserHolderBeanDefinition();applicationContext.registerBeanDefinition("userHolder", userHolderBeanDefinition);// 将 User Bean 初始化XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";// 加载 XML 资源,解析并生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlResourcePath);// 启动 Spring 应用上下文applicationContext.refresh();UserHolder userHolder = applicationContext.getBean(UserHolder.class);System.out.println(userHolder);// 关闭 Spring 应用上下文applicationContext.close();}/*** 为 UserHolder 生成 BeanDefinition** @return {@link BeanDefinition}*/private static BeanDefinition createUserHolderBeanDefinition() {// API 用的就是下述代码BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);// 类似 xml 文件中 「constructor-arg」beanDefinitionBuilder.addConstructorArgReference("superUser");AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();return beanDefinition;}}
dependency-lookup-context.xml
<?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="user" class="com.mindartisan.spring.geek.ioc.overview.domain.User" autowire="byName"><property name="id" value="1"/><property name="name" value="Steve"/></bean><bean id="superUser" class="com.mindartisan.spring.geek.ioc.overview.domain.SuperUser" parent="user"primary="true"><property name="address" value="北京"/></bean><!-- 延迟查找使用 --><bean id="objectFactoryCreatingFactoryBean"class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean"><property name="targetBeanName" value="user"/></bean></beans>
自动方式
- constructor
相关代码:
AutoWiringConstructorDependencyConstructorInjectionDemo.class
/*** byName Autowiring 依赖 Constructor 注入示例** @author mindartisan.blog.csdn.net* @date*/public class AutoWiringConstructorDependencyConstructorInjectionDemo {public static void main(String[] args) {DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);String xmlResourcePath = "classpath:/META-INF/autowiring-dependency-constructor-injection.xml";// 加载 XML 资源,解析并生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlResourcePath);// 依赖查找并创建 BeanUserHolder userHolder = defaultListableBeanFactory.getBean(UserHolder.class);System.out.println(userHolder);}}
autowiring-dependency-constructor-injection.xml
<?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"><import resource="classpath:/META-INF/dependency-lookup-context.xml"/><bean class="com.mindartisan.spring.geek.ioc.dependency.injection.UserHolder" autowire="constructor"></bean></beans>
字段注入
手动模式
- @Autowired
- @Resource
- @Inject(可选)
相关代码:
AnnotationDependencyFieldInjectionDemo.class
/*** 基于注解的依赖 字段 注入示例** @author mindartisan.blog.csdn.net* @date*/public class AnnotationDependencyFieldInjectionDemo {@Autowiredprivate// static // 会忽略掉静态字段UserHolder userHolder;@Resource// 静态字段直接报错private UserHolder userHolder2;public static void main(String[] args) {// 创建 BeanFactory 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 配置类(配置类也是 Spring 的 Bean)applicationContext.register(AnnotationDependencyFieldInjectionDemo.class);// 将 User Bean 初始化,供 userHolder(User user) 使用XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";// 加载 XML 资源,解析并生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlResourcePath);// 启动 Spring 应用上下文applicationContext.refresh();// 依赖查找 AnnotationDependencyFieldInjectionDemo beanAnnotationDependencyFieldInjectionDemo demoBean = applicationContext.getBean(AnnotationDependencyFieldInjectionDemo.class);// 通过 @Autowired 将字段关联UserHolder userHolder = demoBean.userHolder;System.out.println(userHolder);UserHolder userHolder2 = demoBean.userHolder2;System.out.println(userHolder2);// 单例情况下,两个相同,trueSystem.out.println(userHolder2 == userHolder);// 关闭 Spring 应用上下文applicationContext.close();}@Beanpublic UserHolder userHolder(User user) {return new UserHolder(user);}}
dependency-lookup-context.xml
<?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="user" class="com.mindartisan.spring.geek.ioc.overview.domain.User" autowire="byName"><property name="id" value="1"/><property name="name" value="Steve"/></bean><bean id="superUser" class="com.mindartisan.spring.geek.ioc.overview.domain.SuperUser" parent="user"primary="true"><property name="address" value="北京"/></bean><!-- 延迟查找使用 --><bean id="objectFactoryCreatingFactoryBean"class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean"><property name="targetBeanName" value="user"/></bean></beans>
方法注入
手动注入
- @Autowired
- @Resource
- @Inject(可选)
- @Bean
相关代码:
AnnotationDependencyMethodInjectionDemo.class
/*** 基于注解的依赖 方法 注入示例** @author mindartisan.blog.csdn.net* @date*/public class AnnotationDependencyMethodInjectionDemo {private UserHolder userHolder;private UserHolder userHolder2;@Autowiredpublic void method1(UserHolder userHolder) {this.userHolder = userHolder;}@Resourcepublic void method2(UserHolder userHolder) {this.userHolder2 = userHolder;}@Beanpublic UserHolder userHolder(User user) {return new UserHolder(user);}public static void main(String[] args) {// 创建 BeanFactory 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 配置类(配置类也是 Spring 的 Bean)applicationContext.register(AnnotationDependencyMethodInjectionDemo.class);// 将 User Bean 初始化,供 userHolder(User user) 使用XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";// 加载 XML 资源,解析并生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlResourcePath);// 启动 Spring 应用上下文applicationContext.refresh();// 依赖查找 AnnotationDependencyFieldInjectionDemo beanAnnotationDependencyMethodInjectionDemo demoBean = applicationContext.getBean(AnnotationDependencyMethodInjectionDemo.class);// 通过 @Autowired 将字段关联UserHolder userHolder = demoBean.userHolder;System.out.println(userHolder);UserHolder userHolder2 = demoBean.userHolder2;System.out.println(userHolder2);// 单例情况下,两个相同,trueSystem.out.println(userHolder2 == userHolder);// 关闭 Spring 应用上下文applicationContext.close();}}
dependency-lookup-context.xml
<?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="user" class="com.mindartisan.spring.geek.ioc.overview.domain.User" autowire="byName"><property name="id" value="1"/><property name="name" value="Steve"/></bean><bean id="superUser" class="com.mindartisan.spring.geek.ioc.overview.domain.SuperUser" parent="user"primary="true"><property name="address" value="北京"/></bean><!-- 延迟查找使用 --><bean id="objectFactoryCreatingFactoryBean"class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean"><property name="targetBeanName" value="user"/></bean></beans>
回调注入
Aware 系列接口回调
| 内建接口 | 说明 | 备注 |
|---|---|---|
| BeanFactoryAware | 获取 IoC 容器 - BeanFactory | |
| ApplicationContextAware | 获取 Spring 应用上下文 - ApplicationContext 对象 | |
| EnvironmentAware | 获取 Environment 对象 | |
| ResourceLoaderAware | 获取资源加载器 对象 - ResourceLoader | |
| BeanClassLoaderAware | 获取加载当前 Bean Class 的 ClassLoader | |
| BeanNameAware | 获取当前 Bean 的名称 | |
| MessageSourceAware | 获取 MessageSource 对象,用于 Spring 国际化 | |
| ApplicationEventPublisherAware | 获取 ApplicationEventPublishAware 对象,用于 Spring 事件 | |
| EmbeddedValueResolverAware | 获取 StringValueResolver 对象,用于占位符处理 |
相关代码:
AwarelnterfaceDependencyInjectionDemo.class
/*** 基于 Aware 接口回调的依赖注入示例** @author mindartisan.blog.csdn.net* @date*/public class AwarelnterfaceDependencyInjectionDemo implements BeanFactoryAware, ApplicationContextAware {private static BeanFactory beanFactory;private static ApplicationContext applicationContext;public static void main(String[] args) {// 创建 BeanFactory 容器AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();// 注册 配置类context.register(AwarelnterfaceDependencyInjectionDemo.class);// 启动 Spring 应用上下文context.refresh();System.out.println(beanFactory == context.getBeanFactory());System.out.println(applicationContext == context);// 关闭 Spring 应用上下文context.close();}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {AwarelnterfaceDependencyInjectionDemo.beanFactory = beanFactory;}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {AwarelnterfaceDependencyInjectionDemo.applicationContext = applicationContext;}}
依赖注入类型选择
低依赖: 构造器注入,如果构造器的参数过多就不适合使用构造器注入
多依赖:Setter 方法注入,注入的时间顺序依赖与用户操作,如果字段或者依赖的属性存在依赖关系,可能会有问题
便利性:字段注入
声明类:方法注入,一般使用 @Bean 方法注入
基础类型注入
原生类型(Primitive):boolean、byte、char、short、int、float、long、double
标量类型(Scalar):Number、Character、Boolean、Enum、Locale、Charset、Currency、Properties、UUID
常规类型(General):Object、String、TimeZone、Calendar、Optional 等
Spring 类型:Resource、InputSource、Formatter 等
相关代码:
UserForBasicInject.class
/*** 用户--用于演示基本类型注入** @author mindartisan.blog.csdn.net* @date*/public class UserForBasicInject {private Long id;private String name;private City city;// City 和 Resource 相关用于演示基本类型注入public City getCity() {return city;}public void setCity(City city) {this.city = city;}private Resource configFileLocation;public Resource getConfigFileLocation() {return configFileLocation;}public void setConfigFileLocation(Resource configFileLocation) {this.configFileLocation = configFileLocation;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", city=" + city +", configFileLocation=" + configFileLocation +'}';}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}// @Override// public String toString() {// return "User{" +// "id=" + id +// ", name='" + name + '\'' +// '}';// }/*** 通过静态方法实例化** @return {@link UserForBasicInject}*/public static UserForBasicInject createUser(){UserForBasicInject user = new UserForBasicInject();user.setId(1L);user.setName("Steve");return user;}}
City.class
/*** 城市--用来作为 User 属性演示基本类型注入** @author mindartisan.blog.csdn.net* @date*/public enum City {BEIJING,SHANGHAI,GUANGZHOU}
dependency-lookup-context-basic-inject.xml
<?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="userForBasicInject" class="com.mindartisan.spring.geek.ioc.overview.domain.UserForBasicInject" autowire="byName"><property name="id" value="1"/><property name="name" value="Steve"/><!--City 和 configFileLocation 用于演示基本类型注入--><property name="city" value="BEIJING"/><property name="configFileLocation" value="classpath:/META-INF/user-config.properties"/></bean><bean id="superUserForBasicInject" class="com.mindartisan.spring.geek.ioc.overview.domain.SuperUserForBasicInject" parent="userForBasicInject"primary="true"><property name="address" value="北京"/></bean><!--延迟查找使用--><bean id="objectFactoryCreatingFactoryBean"class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean"><property name="targetBeanName" value="userForBasicInject"/></bean></beans>
DependencyLookUpDemoForBasicInject.class
/*** 依赖查找示例--用于演示基础类型注入** @author mindartisan.blog.csdn.net* @date*/public class DependencyLookUpDemoForBasicInject {public static void main(String[] args) {// 配置 XML 配置文件,两个方式均可// 启动 Spring 应用上下文BeanFactory beanFactory = new ClassPathXmlApplicationContext("META-INF/dependency-lookup-context-basic-inject.xml");// BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup-context.xml");lookupInRealTime(beanFactory);lookupInLazy(beanFactory);lookupSingleByType(beanFactory);lookupCollectionByType(beanFactory);lookupByAnnotationType(beanFactory);}/*** 通过名称:实时查找** @param beanFactory bean工厂*/private static void lookupInRealTime(BeanFactory beanFactory) {UserForBasicInject user = (UserForBasicInject) beanFactory.getBean("userForBasicInject");System.out.println("通过名称,实时查找:" + user);}/*** 通过名称:延迟查找** @param beanFactory bean工厂*/private static void lookupInLazy(BeanFactory beanFactory) {ObjectFactory<UserForBasicInject> objectFactoryCreatingFactoryBean = (ObjectFactory<UserForBasicInject>) beanFactory.getBean("objectFactoryCreatingFactoryBean");UserForBasicInject user = objectFactoryCreatingFactoryBean.getObject();System.out.println("通过名称,延迟查找:" + user);}/*** 按类型查找:单个 bean** @param beanFactory bean工厂*/private static void lookupSingleByType(BeanFactory beanFactory) {UserForBasicInject user = beanFactory.getBean(UserForBasicInject.class);System.out.println("按类型查找,单个 bean:" + user);}/*** 按类型查找:多个 bean** @param beanFactory bean工厂*/private static void lookupCollectionByType(BeanFactory beanFactory) {if (beanFactory instanceof ListableBeanFactory) {ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;// key 为 bean 名称Map<String, UserForBasicInject> users = listableBeanFactory.getBeansOfType(UserForBasicInject.class);System.out.println("按类型查找,多个 bean:" + users);}}/*** 按注解查找** @param beanFactory bean工厂*/private static void lookupByAnnotationType(BeanFactory beanFactory) {if (beanFactory instanceof ListableBeanFactory) {ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;// key 为 bean 名称Map<String, User> users = (Map) listableBeanFactory.getBeansWithAnnotation(Super.class);System.out.println("按注解查找:" + users);}}}
SuperUserForBasicInject.class
/*** 超级用户--用于演示基础类型注入** @author mindartisan.blog.csdn.net* @date*/@Superpublic class SuperUserForBasicInject extends UserForBasicInject {private String address;public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}@Overridepublic String toString() {return "SuperUser{" +"address='" + address + '\'' +"} " + super.toString();}}
集合类型注入
数组类型(Array):原生类型、标量类型、常规类型、Spring 类型
集合类型(Collection):
- Collection:List、Set(SortedSet、NavigableSet、EnumSet)
- Map:Properties
相关代码:
City.class,复用基础类型注入
UserForCollectionInject.class
/*** 用户--用于演示集合类型注入** @author mindartisan.blog.csdn.net* @date*/public class UserForCollectionInject {private Long id;private String name;private City city;private City[] workCities;private List<City> lifeCities;public City[] getWorkCities() {return workCities;}public void setWorkCities(City[] workCities) {this.workCities = workCities;}public List<City> getLifeCities() {return lifeCities;}public void setLifeCities(List<City> lifeCities) {this.lifeCities = lifeCities;}// City 和 Resource 相关用于演示基本类型注入public City getCity() {return city;}public void setCity(City city) {this.city = city;}private Resource configFileLocation;public Resource getConfigFileLocation() {return configFileLocation;}public void setConfigFileLocation(Resource configFileLocation) {this.configFileLocation = configFileLocation;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "UserForCollectionInject{" +"id=" + id +", name='" + name + '\'' +", city=" + city +", workCities=" + Arrays.toString(workCities) +", lifeCities=" + lifeCities +", configFileLocation=" + configFileLocation +'}';}// @Override// public String toString() {// return "User{" +// "id=" + id +// ", name='" + name + '\'' +// '}';// }/*** 通过静态方法实例化** @return {@link UserForCollectionInject}*/public static UserForCollectionInject createUser(){UserForCollectionInject user = new UserForCollectionInject();user.setId(1L);user.setName("Steve");return user;}}
DependencyLookUpDemoForCollectionInject.class
/*** 依赖查找示例--用于演示集合类型注入** @author mindartisan.blog.csdn.net* @date*/public class DependencyLookUpDemoForCollectionInject {public static void main(String[] args) {// 配置 XML 配置文件,两个方式均可// 启动 Spring 应用上下文BeanFactory beanFactory = new ClassPathXmlApplicationContext("META-INF/dependency-lookup-context-collection" +"-inject" +".xml");// BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup-context.xml");lookupInRealTime(beanFactory);lookupInLazy(beanFactory);lookupSingleByType(beanFactory);lookupCollectionByType(beanFactory);lookupByAnnotationType(beanFactory);}/*** 通过名称:实时查找** @param beanFactory bean工厂*/private static void lookupInRealTime(BeanFactory beanFactory) {UserForCollectionInject user = (UserForCollectionInject) beanFactory.getBean("userForCollectionInject");System.out.println("通过名称,实时查找:" + user);}/*** 通过名称:延迟查找** @param beanFactory bean工厂*/private static void lookupInLazy(BeanFactory beanFactory) {ObjectFactory<UserForCollectionInject> objectFactoryCreatingFactoryBean = (ObjectFactory<UserForCollectionInject>) beanFactory.getBean("objectFactoryCreatingFactoryBean");UserForCollectionInject user = objectFactoryCreatingFactoryBean.getObject();System.out.println("通过名称,延迟查找:" + user);}/*** 按类型查找:单个 bean** @param beanFactory bean工厂*/private static void lookupSingleByType(BeanFactory beanFactory) {UserForCollectionInject user = beanFactory.getBean(UserForCollectionInject.class);System.out.println("按类型查找,单个 bean:" + user);}/*** 按类型查找:多个 bean** @param beanFactory bean工厂*/private static void lookupCollectionByType(BeanFactory beanFactory) {if (beanFactory instanceof ListableBeanFactory) {ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;// key 为 bean 名称Map<String, UserForCollectionInject> users = listableBeanFactory.getBeansOfType(UserForCollectionInject.class);System.out.println("按类型查找,多个 bean:" + users);}}/*** 按注解查找** @param beanFactory bean工厂*/private static void lookupByAnnotationType(BeanFactory beanFactory) {if (beanFactory instanceof ListableBeanFactory) {ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;// key 为 bean 名称Map<String, User> users = (Map) listableBeanFactory.getBeansWithAnnotation(Super.class);System.out.println("按注解查找:" + users);}}}
dependency-lookup-context-collection-inject.xml
<?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="userForCollectionInject" class="com.mindartisan.spring.geek.ioc.overview.domain.UserForCollectionInject"autowire="byName"><property name="id" value="1"/><property name="name" value="Steve"/><property name="city" value="BEIJING"/><property name="workCities" value="BEIJING,SHANGHAI"/><!--<property name="lifeCities" value="BEIJING,GUANGZHOU,SHANGHAI"/>--><property name="lifeCities"><list><value>BEIJING</value><value>GUANGZHOU</value><value>SHANGHAI</value></list></property><property name="configFileLocation" value="classpath:/META-INF/user-config.properties"/></bean><bean id="superUserForCollectionInject"class="com.mindartisan.spring.geek.ioc.overview.domain.SuperUserForCollectionInject"parent="userForCollectionInject"primary="true"><property name="address" value="北京"/></bean><!--延迟查找使用--><bean id="objectFactoryCreatingFactoryBean"class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean"><property name="targetBeanName" value="userForCollectionInject"/></bean></beans>
UserForCollectionInject.class
/*** 用户--用于演示集合类型注入** @author mindartisan.blog.csdn.net* @date*/public class UserForCollectionInject {private Long id;private String name;private City city;private City[] workCities;private List<City> lifeCities;public City[] getWorkCities() {return workCities;}public void setWorkCities(City[] workCities) {this.workCities = workCities;}public List<City> getLifeCities() {return lifeCities;}public void setLifeCities(List<City> lifeCities) {this.lifeCities = lifeCities;}// City 和 Resource 相关用于演示基本类型注入public City getCity() {return city;}public void setCity(City city) {this.city = city;}private Resource configFileLocation;public Resource getConfigFileLocation() {return configFileLocation;}public void setConfigFileLocation(Resource configFileLocation) {this.configFileLocation = configFileLocation;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "UserForCollectionInject{" +"id=" + id +", name='" + name + '\'' +", city=" + city +", workCities=" + Arrays.toString(workCities) +", lifeCities=" + lifeCities +", configFileLocation=" + configFileLocation +'}';}// @Override// public String toString() {// return "User{" +// "id=" + id +// ", name='" + name + '\'' +// '}';// }/*** 通过静态方法实例化** @return {@link UserForCollectionInject}*/public static UserForCollectionInject createUser(){UserForCollectionInject user = new UserForCollectionInject();user.setId(1L);user.setName("Steve");return user;}}
限定注入
使用注解 @Qualifier 限定
- 通过 Bean 名称限定
- 通过分组限定
相关代码:
QualifierAnnotationDependencyInjectDemo.class
/*** Qualifier 注解依赖注入示例** @author mindartisan.blog.csdn.net* @date*/public class QualifierAnnotationDependencyInjectDemo {@Autowired // 会注入 superUser,因为 primary = trueprivate User user;@Autowired@Qualifier("user") // 指定 bean 名称或者 idprivate User namedUser;@Bean@Qualifier // 逻辑分组public User user1() {return createUser(101L);}@Bean@Qualifier // 逻辑分组public User user2() {return createUser(102L);}// 上述定义了 4 个 User 类型的 Bean:superUser、user、user1、user2@Autowiredprivate Collection<User> allUsers; // 两个 Bean:user+namedUser@Autowired@Qualifier // 逻辑分组private Collection<User> qualifierUsers; // 没用 @UserGroup 之前:2 个 bean 标注了 @Qualifier 注解的 user1 user2;用了之后 4// 个:user1、user2、user3、user4// 下述演示 @Qualifier 分组限定private static User createUser(Long id) {User user = new User();user.setId(id);return user;}@Bean@UserGrouppublic User user3() {return createUser(103L);}@Bean@UserGrouppublic User user4() {return createUser(104L);}@Bean@UserGrouppublic User user5() {return createUser(105L);}@Autowired@UserGroupprivate Collection<User> userGroup; // 3 个 Bean,user3、user4、user5public static void main(String[] args) {// 创建 BeanFactory 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 配置类(配置类也是 Spring 的 Bean)applicationContext.register(QualifierAnnotationDependencyInjectDemo.class);// 将 User Bean 初始化,供 userHolder(User user) 使用XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";// 加载 XML 资源,解析并生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlResourcePath);// 启动 Spring 应用上下文applicationContext.refresh();// 依赖查找 AnnotationDependencyFieldInjectionDemo beanQualifierAnnotationDependencyInjectDemo demoBean = applicationContext.getBean(QualifierAnnotationDependencyInjectDemo.class);System.out.println("demoBean.user" + demoBean.user);System.out.println("demoBean.namedUser" + demoBean.namedUser);System.out.println("demoBean.allUsers" + demoBean.allUsers);System.out.println("demoBean.qualifierUsers" + demoBean.qualifierUsers);System.out.println("demoBean.userGroup" + demoBean.userGroup);// 关闭 Spring 应用上下文applicationContext.close();}}
UserGroup.class
/*** 用户组 注解,扩展 @Qualifier** @author mindartisan.blog.csdn.net* @date*/@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)@Inherited@Documented@Qualifierpublic @interface UserGroup {}
基于注解 @Qualifier 扩展限定
- 自定义注解:如 Spring Cloud 的 @LoadBalanced

一个有 负载均衡 能力的 RestTemplate,一个没有 负载均衡 能力的 RestTemplate
延迟依赖注入
使用 API ObjectFactory 延迟注入
使用 API ObjectProvider 延迟注入(推荐)
单一类型、集合类型
相关代码:
LazyAnnotationDependencyInjectDemo.class
/*** 使用 ObjectProvider 实现延迟注入** @author mindartisan.blog.csdn.net* @date*/public class LazyAnnotationDependencyInjectDemo {@Autowiredprivate User user; // 实时注入@Autowiredprivate ObjectProvider<User> userObjectProvider;@Autowiredprivate ObjectFactory<Collection<User>> collectionObjectFactory;public static void main(String[] args) {// 创建 BeanFactory 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 配置类(配置类也是 Spring 的 Bean)applicationContext.register(LazyAnnotationDependencyInjectDemo.class);// 将 User Bean 初始化,供 userHolder(User user) 使用XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";// 加载 XML 资源,解析并生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlResourcePath);// 启动 Spring 应用上下文applicationContext.refresh();// 依赖查找 AnnotationDependencyFieldInjectionDemo beanLazyAnnotationDependencyInjectDemo demoBean = applicationContext.getBean(LazyAnnotationDependencyInjectDemo.class);System.out.println("demoBean.user" + demoBean.user);System.out.println("demoBean.userObjectProvider" + demoBean.userObjectProvider.getObject());System.out.println("------");demoBean.userObjectProvider.forEach(System.out::println);System.out.println("-------");System.out.println("demoBean.collectionObjectFactory" + demoBean.collectionObjectFactory.getObject());demoBean.collectionObjectFactory.getObject().forEach(System.out::println);// 关闭 Spring 应用上下文applicationContext.close();}}
依赖处理过程
基础知识
入口:DefaultListableBeanFactory#resolveDependency
依赖描述符:DependencyDescriptor
自动绑定候选对象处理器:AutowireCandidateResolver
DependencyDescriptor
public class DependencyDescriptor extends InjectionPoint implements Serializable {private final Class<?> declaringClass; // 当前要注入的容器(声明的类)@Nullable // 可以为空,Spring 注解private String methodName; // 方法名称@Nullable // 可以为空,Spring 注解private Class<?>[] parameterTypes; // 构造器参数或方法参数private int parameterIndex; // 参数的索引@Nullable // 可以为空,Spring 注解private String fieldName; // 属性名private final boolean required; //@Autowired 注解的 required 对应private final boolean eager; // 是否延迟:Lazy = true -> eager = falseprivate int nestingLevel = 1;@Nullableprivate Class<?> containingClass; // 注入到哪个类里了@Nullableprivate transient volatile ResolvableType resolvableType; // Spring 的泛型输出@Nullableprivate transient volatile TypeDescriptor typeDescriptor;// 省略方法}
相关代码:
AnnotationDependencyInjectResolutionDemo.class
/*** 注解驱动的依赖注入处理流程示例** @author mindartisan.blog.csdn.net* @date*/public class AnnotationDependencyInjectResolutionDemo {/*** 单一注入:* 依赖应找(处理)* DependencyDescriptor->* 必须(required = true)* 实时注入(eager=true)* 通过类型(User.class)* 字段名称(“user")* 是否首要(primary = true)*/@Autowiredprivate User user;public static void main(String[] args) {// 创建 BeanFactory 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 配置类(配置类也是 Spring 的 Bean)applicationContext.register(AnnotationDependencyInjectResolutionDemo.class);// 将 User Bean 初始化,供 userHolder(User user) 使用XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";// 加载 XML 资源,解析并生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlResourcePath);// 启动 Spring 应用上下文applicationContext.refresh();// 依赖查找 AnnotationDependencyFieldInjectionDemo beanAnnotationDependencyInjectResolutionDemo demoBean = applicationContext.getBean(AnnotationDependencyInjectResolutionDemo.class);System.out.println("demoBean.user" + demoBean.user);// 关闭 Spring 应用上下文applicationContext.close();}}
debug 验证
断点位置:DefaultListableBeanFactory#resolveDependency() -> descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
@Override@Nullablepublic Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {// 断点在下一行descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());if (Optional.class == descriptor.getDependencyType()) {return createOptionalDependency(descriptor, requestingBeanName);}else if (ObjectFactory.class == descriptor.getDependencyType() ||ObjectProvider.class == descriptor.getDependencyType()) {return new DependencyObjectProvider(descriptor, requestingBeanName);}else if (javaxInjectProviderClass == descriptor.getDependencyType()) {return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);}else {Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);if (result == null) {result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);}return result;}}
在当前示例下,前几个 if 都为 false,直接进入最后的 else,result 此时也会为 null,直接进入 doResolveDependency()查看。
断点位置:DefaultListableBeanFactory#doResolveDependency() -> InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
@Nullablepublic Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {// 断点在下一行InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);try {Object shortcut = descriptor.resolveShortcut(this);if (shortcut != null) {return shortcut;}Class<?> type = descriptor.getDependencyType();Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);if (value != null) {if (value instanceof String) {String strVal = resolveEmbeddedValue((String) value);BeanDefinition bd = (beanName != null && containsBean(beanName) ?getMergedBeanDefinition(beanName) : null);value = evaluateBeanDefinitionString(strVal, bd);}TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());try {return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());}catch (UnsupportedOperationException ex) {// A custom TypeConverter which does not support TypeDescriptor resolution...return (descriptor.getField() != null ?converter.convertIfNecessary(value, type, descriptor.getField()) :converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));}}// 是否多个 BeanObject multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);if (multipleBeans != null) {return multipleBeans;}// 此时会有两个 bean:user、superUserMap<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);if (matchingBeans.isEmpty()) {if (isRequired(descriptor)) {raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}return null;}String autowiredBeanName;Object instanceCandidate;if (matchingBeans.size() > 1) {autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);if (autowiredBeanName == null) {if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);}else {// In case of an optional Collection/Map, silently ignore a non-unique case:// possibly it was meant to be an empty collection of multiple regular beans// (before 4.3 in particular when we didn't even look for collection beans).return null;}}instanceCandidate = matchingBeans.get(autowiredBeanName);}else {// We have exactly one match.Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();autowiredBeanName = entry.getKey();instanceCandidate = entry.getValue();}if (autowiredBeanNames != null) {autowiredBeanNames.add(autowiredBeanName);}if (instanceCandidate instanceof Class) {instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);}Object result = instanceCandidate;if (result instanceof NullBean) {if (isRequired(descriptor)) {raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}result = null;}if (!ClassUtils.isAssignableValue(type, result)) {throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());}return result;}finally {ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);}}
DefaultListableBeanFactory#findAutowireCandidates()
找符合类型的 bean,此例中是 user,会有两个 user 和 superUser
protected Map<String, Object> findAutowireCandidates(@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager());Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {Class<?> autowiringType = classObjectEntry.getKey();if (autowiringType.isAssignableFrom(requiredType)) {Object autowiringValue = classObjectEntry.getValue();autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);if (requiredType.isInstance(autowiringValue)) {result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);break;}}}for (String candidate : candidateNames) {if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {addCandidateEntry(result, candidate, descriptor, requiredType);}}if (result.isEmpty()) {boolean multiple = indicatesMultipleBeans(requiredType);// Consider fallback matches if the first pass failed to find anything...DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();for (String candidate : candidateNames) {if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {addCandidateEntry(result, candidate, descriptor, requiredType);}}if (result.isEmpty() && !multiple) {// Consider self references as a final pass...// but in the case of a dependency collection, not the very same bean itself.for (String candidate : candidateNames) {if (isSelfReference(beanName, candidate) &&(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&isAutowireCandidate(candidate, fallbackDescriptor)) {addCandidateEntry(result, candidate, descriptor, requiredType);}}}}return result;}
DefaultListableBeanFactory#determinePrimaryCandidate()
主要是找 primary bean
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {String primaryBeanName = null;for (Map.Entry<String, Object> entry : candidates.entrySet()) {String candidateBeanName = entry.getKey();Object beanInstance = entry.getValue();if (isPrimary(candidateBeanName, beanInstance)) {if (primaryBeanName != null) {boolean candidateLocal = containsBeanDefinition(candidateBeanName);boolean primaryLocal = containsBeanDefinition(primaryBeanName);if (candidateLocal && primaryLocal) {throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),"more than one 'primary' bean found among candidates: " + candidates.keySet());}else if (candidateLocal) {primaryBeanName = candidateBeanName;}}else {primaryBeanName = candidateBeanName;}}}return primaryBeanName;}
DefaultListableBeanFactory#isPrimary()
在这里利用 BeanDefinition 里的 isPrimary 判断
protected boolean isPrimary(String beanName, Object beanInstance) {String transformedBeanName = transformedBeanName(beanName);if (containsBeanDefinition(transformedBeanName)) {return getMergedLocalBeanDefinition(transformedBeanName).isPrimary();}BeanFactory parent = getParentBeanFactory();return (parent instanceof DefaultListableBeanFactory &&((DefaultListableBeanFactory) parent).isPrimary(transformedBeanName, beanInstance));}
如果在 AnnotationDependencyInjectResolutionDemo.class 添加:
/** 集合注入**/@Autowiredprivate Map<String, User> users;
则可以在 DefaultListableBeanFactory#resolveMultipleBeans() 方法打断点查看,不再赘述。
else if (Map.class == type) {ResolvableType mapType = descriptor.getResolvableType().asMap();Class<?> keyType = mapType.resolveGeneric(0);// 省略代码}
如果在 AnnotationDependencyInjectResolutionDemo.class 添加:
@Autowiredprivate Optional<User> optionalUser;
则可以在 DefaultListableBeanFactory#createOptionalDependency() 方法打断点查看,不再赘述。
if (Optional.class == descriptor.getDependencyType()) {return createOptionalDependency(descriptor, requestingBeanName);}
@Autowired 注入原理
大概流程:
- 元信息解析 -> 和 DependencyDescriptor 相关
- 依赖查找 -> 可以理解为依赖处理的过程
- 依赖注入(注入到方法、字段)
源码解析
以「依赖处理流程」中的代码为例,断点在 DefaultListableBeanFactory#resolveDependency() -> descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
使用 IDEA 的 debug 工具,查看调用栈相关信息:
进入方法:
@Overrideprotected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {Field field = (Field) this.member;Object value;if (this.cached) {value = resolvedCachedArgument(beanName, this.cachedFieldValue);}else {DependencyDescriptor desc = new DependencyDescriptor(field, this.required);desc.setContainingClass(bean.getClass());Set<String> autowiredBeanNames = new LinkedHashSet<>(1);Assert.state(beanFactory != null, "No BeanFactory available");TypeConverter typeConverter = beanFactory.getTypeConverter();try {// 此处进行依赖处理的流程value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);}catch (BeansException ex) {throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);}synchronized (this) {if (!this.cached) {if (value != null || this.required) {this.cachedFieldValue = desc;registerDependentBeans(beanName, autowiredBeanNames);if (autowiredBeanNames.size() == 1) {String autowiredBeanName = autowiredBeanNames.iterator().next();if (beanFactory.containsBean(autowiredBeanName) &&beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {this.cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName, field.getType());}}}else {this.cachedFieldValue = null;}this.cached = true;}}}if (value != null) {// 通过反射的形式对 field 赋值ReflectionUtils.makeAccessible(field);field.set(bean, value);}}
一些细节:
主要引用了 极客时间 Spring IoC 课程 中的一些精选评论。
引用一:
- 在doCreateBean中会先调用applyMergedBeanDefinitionPostProcessors,后执行populateBean 所以会先调用postProcessMergedBeanDefinition后执行InstantiationAwareBeanPostProcessor的postProcessProperties。
- postProcessProperties中有两个步骤:
- findAutowiringMetadata查找注入元数据,没有缓存就创建,具体是上一节内容。最终会返回InjectionMetadata,里面包括待注入的InjectedElement信息(field、method)等等
- 执行InjectionMetadata的inject方法,具体为AutowiredFieldElement和AutowiredMethodElement的Inject方法
- AutowiredFieldElement inject具体流程:
- DependencyDescriptor的创建
- 调用beanFactory的resolveDependency获取带注入的bean
- resolveDependency根据具体类型返回候选bean的集合或primary 的bean
- 利用反射设置field
引用二:
引用三:
JSR-330 @Inject 注入原理
如果 JSR-330 存在与 ClassPath 中,复用AutowiredAnnotationBeanPostProcessor实现 ```java private final Set> autowiredAnnotationTypes = new LinkedHashSet<>(4);
- AutowiredFieldElement inject具体流程:
/**
* Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's* standard {@link Autowired @Autowired} and {@link Value @Value} annotations.* <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,* if available.*/@SuppressWarnings("unchecked")public AutowiredAnnotationBeanPostProcessor() {this.autowiredAnnotationTypes.add(Autowired.class);this.autowiredAnnotationTypes.add(Value.class);try {this.autowiredAnnotationTypes.add((Class<? extends Annotation>)ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");}catch (ClassNotFoundException ex) {// JSR-330 API not available - simply skip.}}
在使用时,优先使用 `@Autowired`,参见:```java@Nullableprivate MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {MergedAnnotations annotations = MergedAnnotations.from(ao);for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {MergedAnnotation<?> annotation = annotations.get(type);if (annotation.isPresent()) {return annotation;}}return null;}
Java 通用注解注入原理
基础知识
基于 CommonAnnotationBeanPostProcessor实现:
- 注入注解
- javax.xml.ws.WebServiceRef
- javax.ejb.EJB
- javax.annotation.Resource
- 生命周期注解
再详细对比下此方法 postProcessMergedBeanDefinition:
// CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);metadata.checkConfigMembers(beanDefinition);}// AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);metadata.checkConfigMembers(beanDefinition);}
再去 super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName) 里看下:
// InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition(beanDefinition, beanType, beanName)@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {LifecycleMetadata metadata = findLifecycleMetadata(beanType);metadata.checkConfigMembers(beanDefinition);}
可以看到,CommonAnotationBeanPostProcessor 比 AutowiredAnnotationBeanPostProcessor 的处理流程其实差不多,当前可以看到多的有LifecycleMetadata 的处理:
/*** Class representing information about annotated init and destroy methods.*/private class LifecycleMetadata {private final Class<?> targetClass;private final Collection<LifecycleElement> initMethods;private final Collection<LifecycleElement> destroyMethods;@Nullableprivate volatile Set<LifecycleElement> checkedInitMethods;@Nullableprivate volatile Set<LifecycleElement> checkedDestroyMethods;public LifecycleMetadata(Class<?> targetClass, Collection<LifecycleElement> initMethods,Collection<LifecycleElement> destroyMethods) {this.targetClass = targetClass;this.initMethods = initMethods;this.destroyMethods = destroyMethods;}}
注入源码解析
回到 Java 通用注解注入原理的问题中来,调用链:
- CommonAnotationBeanPostProcessor#postProcessProperties();
- CommonAnotationBeanPostProcessor#findResourceMetadata();
- CommonAnotationBeanPostProcessor#buildResourceMetadata();
CommonAnotationBeanPostProcessor#buildResourceMetadata() 相关代码:
do {final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();ReflectionUtils.doWithLocalFields(targetClass, field -> {if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {if (Modifier.isStatic(field.getModifiers())) {throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");}currElements.add(new WebServiceRefElement(field, field, null));}else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {if (Modifier.isStatic(field.getModifiers())) {throw new IllegalStateException("@EJB annotation is not supported on static fields");}currElements.add(new EjbRefElement(field, field, null));}else if (field.isAnnotationPresent(Resource.class)) {if (Modifier.isStatic(field.getModifiers())) {throw new IllegalStateException("@Resource annotation is not supported on static fields");}if (!this.ignoredResourceTypes.contains(field.getType().getName())) {currElements.add(new ResourceElement(field, field, null));}}});
回调源码解析
构造器:
/*** Create a new CommonAnnotationBeanPostProcessor,* with the init and destroy annotation types set to* {@link javax.annotation.PostConstruct} and {@link javax.annotation.PreDestroy},* respectively.*/public CommonAnnotationBeanPostProcessor() {setOrder(Ordered.LOWEST_PRECEDENCE - 3);// 下面两行setInitAnnotationType(PostConstruct.class);setDestroyAnnotationType(PreDestroy.class);// 上面两行ignoreResourceType("javax.xml.ws.WebServiceContext");}
public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {this.initAnnotationType = initAnnotationType;}public void setDestroyAnnotationType(Class<? extends Annotation> destroyAnnotationType) {this.destroyAnnotationType = destroyAnnotationType;}
查找 initAnnotationType 的 usage,发现是 CommonAnotationBeanPostProcessor#buildResourceMetadata(),相关代码:
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {return this.emptyLifecycleMetadata;}List<LifecycleElement> initMethods = new ArrayList<>();List<LifecycleElement> destroyMethods = new ArrayList<>();Class<?> targetClass = clazz;do {final List<LifecycleElement> currInitMethods = new ArrayList<>();final List<LifecycleElement> currDestroyMethods = new ArrayList<>();// 重点看此处代码:下述代码会处理被「@PostConstruct 以及 @PreDestroy」的方法ReflectionUtils.doWithLocalMethods(targetClass, method -> {if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {LifecycleElement element = new LifecycleElement(method);currInitMethods.add(element);if (logger.isTraceEnabled()) {logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);}}if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {currDestroyMethods.add(new LifecycleElement(method));if (logger.isTraceEnabled()) {logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);}}});initMethods.addAll(0, currInitMethods);destroyMethods.addAll(currDestroyMethods);targetClass = targetClass.getSuperclass();}while (targetClass != null && targetClass != Object.class);return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :new LifecycleMetadata(clazz, initMethods, destroyMethods));}
再来看下 LifecycleElement:
private static class LifecycleElement {private final Method method;private final String identifier;public LifecycleElement(Method method) {if (method.getParameterCount() != 0) {throw new IllegalStateException("Lifecycle method annotation requires a no-arg method: " + method);}this.method = method;this.identifier = (Modifier.isPrivate(method.getModifiers()) ?ClassUtils.getQualifiedMethodName(method) : method.getName());}public void invoke(Object target) throws Throwable {ReflectionUtils.makeAccessible(this.method);this.method.invoke(target, (Object[]) null);}// 省略部分代码}
查找 invoke 方法的 usages,会发现是 InitDestroyAnnotationBeanPostProcessor#invokeInitMethods() 以及 InitDestroyAnnotationBeanPostProcessor#invokeDestroyMethods()。
再查找上述两个方法的 usage,会发现分别是 postProcessBeforeInitialization()以及 postProcessBeforeDestruction()方法。
CommonAnotationBeanPostProcessor 与 AutowiredAnnotationBeanPostProcessor 顺序
二者都实现了 Ordered接口:
- CommonAnotationBeanPostProcessor 的 order 为
private int order = Ordered.LOWEST_PRECEDENCE - 3;,倒数第四位 - AutowiredAnnotationBeanPostProcessor 的 order 为
private int order = Ordered.LOWEST_PRECEDENCE - 2;,倒数第三位
所以:CommonAnotationBeanPostProcessor 会在 AutowiredAnnotationBeanPostProcessor 使用
自定义依赖注入注解
基于 AutowiredAnnotationBeanPostProcessor 实现
自定义个注解:MyAutowired.class
/*** 自定义注解,利用了 @Autowired** @author mindartisan.blog.csdn.net* @date*/@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Documented@Autowiredpublic @interface MyAutowired {/*** Declares whether the annotated dependency is required.* <p>Defaults to {@code true}.*/boolean required() default true;}
InjectedUser.class
/*** 自定义依赖注入注解** @author mindartisan.blog.csdn.net* @date*/@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface InjectedUser {}
主程序:MyAnnotationDependencyInjectResolutionDemo.class
/*** 注解驱动的依赖注入处理流程示例** @author mindartisan.blog.csdn.net* @date*/public class MyAnnotationDependencyInjectResolutionDemo {/*** 单一注入:* 依赖应找(处理)* DependencyDescriptor->* 必须(required = true)* 实时注入(eager=true)* 通过类型(User.class)* 字段名称(“user")* 是否首要(primary = true)*/@Autowiredprivate User user;@MyAutowiredprivate User myAutowiredUser;@Injectprivate User injectUser;@InjectedUserprivate User myInjectUser;// @Bean(name = AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)// public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {// AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor =// new AutowiredAnnotationBeanPostProcessor();// // 新的自定义注解+自带的实现// // 存在的问题,Inject 或者其他需要的注解不存在// Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(asList(Autowired.class,// Inject.class, InjectedUser.class));// autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationTypes(autowiredAnnotationTypes);// return autowiredAnnotationBeanPostProcessor;// }@Bean@Order(Ordered.LOWEST_PRECEDENCE - 3)public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor =new AutowiredAnnotationBeanPostProcessor();autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationType(InjectedUser.class);return autowiredAnnotationBeanPostProcessor;}public static void main(String[] args) {// 创建 BeanFactory 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 配置类(配置类也是 Spring 的 Bean)applicationContext.register(MyAnnotationDependencyInjectResolutionDemo.class);// 将 User Bean 初始化,供 userHolder(User user) 使用XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";// 加载 XML 资源,解析并生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlResourcePath);// 启动 Spring 应用上下文applicationContext.refresh();// 依赖查找 AnnotationDependencyFieldInjectionDemo beanMyAnnotationDependencyInjectResolutionDemo demoBean = applicationContext.getBean(MyAnnotationDependencyInjectResolutionDemo.class);System.out.println("demoBean.user" + "=" + demoBean.user);System.out.println("demoBean.injectUser" + "=" + demoBean.injectUser);System.out.println("demoBean.myAutowiredUser" + "=" + demoBean.myAutowiredUser);System.out.println("demoBean.myInjectUser" + "=" + demoBean.myInjectUser);// 关闭 Spring 应用上下文applicationContext.close();}}
主要是因为下面的代码(选下面的)
@Bean(name = AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor =new AutowiredAnnotationBeanPostProcessor();// 新的自定义注解+自带的实现// 存在的问题:Inject 或者其他需要的注解不存在Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(asList(Autowired.class,Inject.class, InjectedUser.class));autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationTypes(autowiredAnnotationTypes);return autowiredAnnotationBeanPostProcessor;}@Bean@Order(Ordered.LOWEST_PRECEDENCE - 3)public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor =new AutowiredAnnotationBeanPostProcessor();autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationType(InjectedUser.class);return autowiredAnnotationBeanPostProcessor;}
自定义实现
这里没有讲
生命周期处理:
- InstantiationAwareBeanPostProcessor
- MergedBeanDefinitionPostProcessor
元数据:
- InjectedElement
- InjectionMetadata

