手动模式 - 配置或者编程的方式,提前安排注入规则
自动模式 - 实现方提供依赖自动关联的方式,按照内建的注入规则
依赖注入类型
官方说明
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之间(意思就是依赖类/被依赖类), 通过检查ApplicationContext的内容, 让spring能去处理这些合作者Bean。
优点
Autowiring can significantly reduce the need to specify properties or constructor arguments.
Autowiring 可以有效减少我们一些属性或构造器参数的一个设定
Autowiring can update a configuration as your objects evolve.
自动绑定能更新配置, 就当你的对象正在被逐渐升级或逐渐形成的时候
Autowiring modes
参考枚举: org.springframework. beans.factory.annotation.Autowire
为什么没有构造器模式, 因为构造器模式是一种特殊的BY_TYPE
官方说明
Limitations and Disadvantages of Autowiring
链接: https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/spring-framework-reference/core.html#beans-autowired-exceptions
实现方法
手动模式
XML资源配置元信息
dependency-lookup-context.xml
dependency-setter-injection.xml
UserHolder.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/*** {@link org.xiaoge.thinking.in.spring.ioc.overview.domain.User} Holder 类** @author Zhang Xiao* @since*/
public class UserHolder {private User user;public UserHolder() {}public UserHolder(User user) {this.user = user;}public User getUser() {return user;}public void setUser(User user) {this.user = user;}@Overridepublic String toString() {return "UserHolder{" +"user=" + user +'}';}
}
XmlDependencySetterInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;/*** 基于 XML 资源的依赖 Setter 方法注入 示例** @author Zhang Xiao* @since*/
public class XmlDependencySetterInjectionDemo {public static void main(String[] args) {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);String xmlSourcePath = "classpath:/META-INF/dependency-setter-injection.xml";// 加载 XML 资源, 解析并且生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlSourcePath);// 依赖查找 并且 创建 Bean (注意: 依赖查找的过程中会伴随着创建Bean)UserHolder userHolder = beanFactory.getBean(UserHolder.class);System.out.println(userHolder);}}// 运行结果
UserHolder{user=User{id=1, name='xiaoge'}}
.Java 注解配置元信息
AnnotationDependencySetterInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/*** 基于 注解 资源的依赖 Setter 方法注入 示例** @author Zhang Xiao* @since*/
public class AnnotationDependencySetterInjectionDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(AnnotationDependencySetterInjectionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();UserHolder userHolder = applicationContext.getBean(UserHolder.class);System.out.println(userHolder);// 关闭应用上下文applicationContext.close();}/*** 加@Qualifier是通过Bean名称, 没加是通过Bean类型去找User* @param user* @return*/@Beanpublic UserHolder userHolder(@Qualifier("user") User user) {UserHolder userHolder = new UserHolder();userHolder.setUser(user);return userHolder;}}// 运行结果
UserHolder{user=User{id=1, name='xiaoge'}}
API 配置元信息
ApiDependencySetterInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/*** 基于 API 资源的依赖 Setter 方法注入 示例** @author Zhang Xiao* @since*/
public class ApiDependencySetterInjectionDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 生成 UserHolder 的 BeanDefinitionBeanDefinition userHolderBeanDefinition = createUserHolderBeanDefinition();// 注册 UserHolder 的 BeanDefinitionapplicationContext.registerBeanDefinition("userHolder", userHolderBeanDefinition);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();UserHolder userHolder = applicationContext.getBean(UserHolder.class);System.out.println(userHolder);// 关闭应用上下文applicationContext.close();}/*** 为 {@link UserHolder} 生成 {@link BeanDefinition}* @return*/private static BeanDefinition createUserHolderBeanDefinition() {BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);// 设置属性值beanDefinitionBuilder.addPropertyReference("user", "user");return beanDefinitionBuilder.getBeanDefinition();}}// 运行结果
UserHolder{user=User{id=1, name='xiaoge'}}
自动模式
byName
autowiring-dependency-setter-injection.xml
AutowiringByNameDependencySetterInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;/*** "byName/byType" Autowiring 依赖 setter 注入示例** @author Zhang Xiao* @since*/
public class AutowiringByNameDependencySetterInjectionDemo {public static void main(String[] args) {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);String xmlSourcePath = "classpath:/META-INF/autowiring-dependency-setter-injection.xml";// 加载 XML 资源, 解析并且生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlSourcePath);// 依赖查找 并且 创建 Bean (注意: 依赖查找的过程中会伴随着创建Bean)UserHolder userHolder = beanFactory.getBean(UserHolder.class);System.out.println(userHolder);}}// 运行结果
UserHolder{user=User{id=1, name='xiaoge'}}
byType
autowiring-dependency-setter-injection.xml
AutowiringByNameDependencySetterInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;/*** "byName/byType" Autowiring 依赖 setter 注入示例** @author Zhang Xiao* @since*/
public class AutowiringByNameDependencySetterInjectionDemo {public static void main(String[] args) {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);String xmlSourcePath = "classpath:/META-INF/autowiring-dependency-setter-injection.xml";// 加载 XML 资源, 解析并且生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlSourcePath);// 依赖查找 并且 创建 Bean (注意: 依赖查找的过程中会伴随着创建Bean)UserHolder userHolder = beanFactory.getBean(UserHolder.class);System.out.println(userHolder);}}// 运行结果
UserHolder{user=SuperUser{address='武汉'} User{id=1, name='xiaoge'}}因为superUser加了primary="true"
实现方法
手动模式
XML 资源配置元信
dependency-constructor-injection.xml
1
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;/*** 基于 XML 资源的依赖 Constructor 注入 示例** @author Zhang Xiao* @since*/
public class XmlDependencyConstructorInjectionDemo {public static void main(String[] args) {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);String xmlSourcePath = "classpath:/META-INF/dependency-constructor-injection.xml";// 加载 XML 资源, 解析并且生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlSourcePath);// 依赖查找 并且 创建 Bean (注意: 依赖查找的过程中会伴随着创建Bean)UserHolder userHolder = beanFactory.getBean(UserHolder.class);System.out.println(userHolder);}}// 运行结果
UserHolder{user=SuperUser{address='武汉'} User{id=1, name='xiaoge'}}
Java 注解配置元信息
AnnotationDependencyConstructorInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/*** 基于 注解 资源的依赖 Constructor 注入 示例** @author Zhang Xiao* @since*/
public class AnnotationDependencyConstructorInjectionDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(AnnotationDependencyConstructorInjectionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();UserHolder userHolder = applicationContext.getBean(UserHolder.class);System.out.println(userHolder);// 关闭应用上下文applicationContext.close();}/*** 加@Qualifier是通过Bean名称, 没加是通过Bean类型去找User* @param user* @return*/@Beanpublic UserHolder userHolder(@Qualifier("user") User user) {return new UserHolder(user);}}// 运行结果
UserHolder{user=User{id=1, name='xiaoge'}}
API 配置元信息
ApiDependencyConstructorInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** 基于 API 资源的依赖 Constructor 注入 示例** @author Zhang Xiao* @since*/
public class ApiDependencyConstructorInjectionDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 生成 UserHolder 的 BeanDefinitionBeanDefinition userHolderBeanDefinition = createUserHolderBeanDefinition();// 注册 UserHolder 的 BeanDefinitionapplicationContext.registerBeanDefinition("userHolder", userHolderBeanDefinition);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();UserHolder userHolder = applicationContext.getBean(UserHolder.class);System.out.println(userHolder);// 关闭应用上下文applicationContext.close();}/*** 为 {@link UserHolder} 生成 {@link BeanDefinition}* @return*/private static BeanDefinition createUserHolderBeanDefinition() {BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);// 构造器设置属性值, 这个只有一个参数, 构造器如果有3个参数, 依次调三次这个方法addConstructorArgReference, 我这里只有一个所以写一次beanDefinitionBuilder.addConstructorArgReference("superUser");return beanDefinitionBuilder.getBeanDefinition();}}// 运行结果
UserHolder{user=SuperUser{address='武汉'} User{id=1, name='xiaoge'}}
自动模式
constructor
autowiring-dependency-constructor-injection.xml
AutowiringConstructorDependencyConstructorInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;/*** "constructor" Autowiring 依赖 Constructor 注入示例** @author Zhang Xiao* @since*/
public class AutowiringConstructorDependencyConstructorInjectionDemo {public static void main(String[] args) {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);String xmlSourcePath = "classpath:/META-INF/autowiring-dependency-constructor-injection.xml";// 加载 XML 资源, 解析并且生成 BeanDefinitionxmlBeanDefinitionReader.loadBeanDefinitions(xmlSourcePath);// 依赖查找 并且 创建 Bean (注意: 依赖查找的过程中会伴随着创建Bean)UserHolder userHolder = beanFactory.getBean(UserHolder.class);System.out.println(userHolder);}}// 运行结果
UserHolder{user=SuperUser{address='武汉'} User{id=1, name='xiaoge'}}
实现方法
手动模式
Java 注解配置元信息
@Autowired
@Resource
@Inject(可选)
AnnotationDependencyFieldInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;import javax.annotation.Resource;/*** 基于 注解 资源的依赖 Field 注入 示例** @author Zhang Xiao* @since*/
public class AnnotationDependencyFieldInjectionDemo {@Autowiredprivate// static @Autowired 会忽略掉静态字段 所以加嘞static userHolder为nullUserHolder userHolder;@Resource // @Resource 标注的字段同理 不能为static 为static就会报错private UserHolder userHolder2;public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(AnnotationDependencyFieldInjectionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();AnnotationDependencyFieldInjectionDemo demo = applicationContext.getBean(AnnotationDependencyFieldInjectionDemo.class);System.out.println(demo.userHolder);System.out.println(demo.userHolder2);System.out.println(demo.userHolder == demo.userHolder2);// 关闭应用上下文applicationContext.close();}/*** 加@Qualifier是通过Bean名称, 没加是通过Bean类型去找User* @param user* @return*/@Beanpublic UserHolder userHolder(@Qualifier("user") User user) {return new UserHolder(user);}}// 运行结果
UserHolder{user=User{id=1, name='xiaoge'}}
UserHolder{user=User{id=1, name='xiaoge'}}
true
所以这里指的字段注入, 是指的实例字段/对象字段
实现方法
手动模式
Java 注解配置元信息
@Autowired
@Resource
@Inject(可选)
@Bean
AnnotationDependencyMethodInjectionDemo
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;import javax.annotation.Resource;/*** 基于 注解 资源的依赖 Method 注入 示例** @author Zhang Xiao* @since*/
public class AnnotationDependencyMethodInjectionDemo {private UserHolder userHolder;private UserHolder userHolder2;@Autowiredpublic void initUserHolder(UserHolder userHolder) {this.userHolder = userHolder;}@Resourcepublic void initUserHolder2(UserHolder userHolder2) {this.userHolder2 = userHolder2;}/*** 加@Qualifier是通过Bean名称, 没加是通过Bean类型去找User* @param user* @return*/@Beanpublic UserHolder userHolder(@Qualifier("user") User user) {return new UserHolder(user);}public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(AnnotationDependencyMethodInjectionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();AnnotationDependencyMethodInjectionDemo demo = applicationContext.getBean(AnnotationDependencyMethodInjectionDemo.class);System.out.println(demo.userHolder);System.out.println(demo.userHolder2);System.out.println(demo.userHolder == demo.userHolder2);// 关闭应用上下文applicationContext.close();}}// 运行结果
UserHolder{user=User{id=1, name='xiaoge'}}
UserHolder{user=User{id=1, name='xiaoge'}}
true
注意: 方法注入只关注方法参数类型(不关注方法名称, 方法名称可以随便写), 它会去spring上下文中去找对应类型的对象赋值给方法的参数
Aware 系列接口回调
自动模式
AwareInterfaceDependencyInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.Aware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** 基于 ${@link Aware} 接口回调的依赖注入 示例** @author Zhang Xiao* @since*/
public class AwareInterfaceDependencyInjectionDemo implements BeanFactoryAware, ApplicationContextAware {private static BeanFactory beanFactory;private static ApplicationContext applicationContext;public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类 -> springBeancontext.register(AwareInterfaceDependencyInjectionDemo.class);// 启动应用上下文context.refresh();/*因为 AnnotationConfigApplicationContext 本身没有能力去获取Bean它是通过context.getBeanFactory()获取DefaultListableBeanFactory对象去查询bean*/System.out.println(AwareInterfaceDependencyInjectionDemo.beanFactory == context.getBeanFactory());System.out.println(applicationContext == context);// 关闭应用上下文context.close();}public void setBeanFactory(BeanFactory beanFactory) throws BeansException {AwareInterfaceDependencyInjectionDemo.beanFactory = beanFactory;}public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {AwareInterfaceDependencyInjectionDemo.applicationContext = applicationContext;}
}// 运行结果
true
true
基础类型
原生类型(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 等
resource为什么打印出来会有class path resource因为它是掉的ClassPathResource的toString方法
集合类型
数组类型(Array):原生类型、标量类型、常规类型、Spring 类
集合类型(Collection)
Collection:List、Set(SortedSet、NavigableSet、EnumSet)
Map:Properties
User.java
package org.xiaoge.thinking.in.spring.ioc.overview.domain;import org.omg.CORBA.PRIVATE_MEMBER;
import org.springframework.core.io.Resource;
import org.xiaoge.thinking.in.spring.ioc.overview.Enum.City;import java.util.Arrays;
import java.util.List;
import java.util.Map;/*** @Classname User* @Date 2022/10/17 14:57* @Created by ZhangXiao* @Description TODO*/
public class User {private Long id;private String name;private City city;private Resource configFileLocation;private City[] workCities;private List lifeCities;private Map
dependency-lookup-context.xml
WUHAN BEIJING
DependencyLookupDemo.java
package org.xiaoge.thinking.in.spring.ioc.overview.dependency.lookup;import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.xiaoge.thinking.in.spring.ioc.overview.annotation.Super;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;import java.util.Map;/*** 依赖查找示例* 1. 通过名称的方式查找* 1. 实时查找 lookupInRealTime* 2. 延迟查找 lookupInLazy* 2. 根据类型查找* 1. 根据类型查找单个bean lookupByType* 2. 根据类型查找集合对象Map lookupCollectionByType* 3. 根据java注解查找* 1. 单个bean对象/集合bean对象 lookupAnnotationByType** @Classname DependencyLookupDemo* @Date 2022/10/17 14:56* @Created by ZhangXiao* @Description TODO*/
public class DependencyLookupDemo {public static void main(String[] args) {// 配置xml配置文件// 启动spring应用上下文BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:META-INF/dependency-lookup-context.xml");lookupInRealTime(beanFactory);lookupInLazy(beanFactory);lookupByType(beanFactory);lookupCollectionByType(beanFactory);lookupAnnotationByType(beanFactory);}/*** 根据注解查找集合对象* @param beanFactory*/private static void lookupAnnotationByType(BeanFactory beanFactory) {if (beanFactory instanceof ListableBeanFactory) {ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;Map map = (Map)listableBeanFactory.getBeansWithAnnotation(Super.class);System.out.println("查找所有标注: @Super 所有的 user 集合对象: " + map);}}/*** 根据类型查找集合对象* @param beanFactory*/private static void lookupCollectionByType(BeanFactory beanFactory) {if (beanFactory instanceof ListableBeanFactory) {ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;Map map = listableBeanFactory.getBeansOfType(User.class);System.out.println("查找到所有的 user 集合对象: " + map);}}/*** 根据类型实时查找* @param beanFactory*/private static void lookupByType(BeanFactory beanFactory) {User user = beanFactory.getBean(User.class);System.out.println("实时查找: " + user);}/*** 延迟加载bean* @param beanFactory*/public static void lookupInLazy(BeanFactory beanFactory) {ObjectFactory objectFactory = (ObjectFactory)beanFactory.getBean("objectFactory");User user = objectFactory.getObject();System.out.println("延迟查找: " + user);}/*** 实施加载bean* @param beanFactory*/public static void lookupInRealTime(BeanFactory beanFactory) {User user = (User)beanFactory.getBean("user");System.out.println("实时查找: " + user);}
}// 运行结果
实时查找: User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
延迟查找: User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
实时查找: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
查找到所有的 user 集合对象: {user=User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, superUser=SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}}
查找所有标注: @Super 所有的 user 集合对象: {superUser=SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}}
使用注解 @Qualifier 限定
通过 Bean 名称限定
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/*** {@link Qualifier} 注解依赖注入** @author Zhang Xiao* @see Qualifier* @since*/
public class QualifierAnnotationDependencylrjectionDemo {@Autowiredprivate User user; // super user -> primary = true@Autowired@Qualifier("user")private User namedUser; // 指定 Bean 名称 或 IDpublic static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(QualifierAnnotationDependencylrjectionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();QualifierAnnotationDependencylrjectionDemo demo = applicationContext.getBean(QualifierAnnotationDependencylrjectionDemo.class);System.out.println("demo.user: " + demo.user);System.out.println("demo.namedUser: " + demo.namedUser);// 关闭应用上下文applicationContext.close();}}// 运行结果
demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.namedUser: User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
通过分组限定
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;import java.util.Collection;/*** {@link Qualifier} 注解依赖注入** @author Zhang Xiao* @see Qualifier* @since*/
public class QualifierAnnotationDependencylrjectionDemo {@Autowiredprivate User user; // super user -> primary = true@Autowired@Qualifier("user")private User namedUser; // 指定 Bean 名称 或 ID@Autowired // 只会获取不带Qualifier的Beanprivate Collection allUsers; // 2 Bean -> super user, user@Autowired@Qualifier // 只会获取带Qualifier的Beanprivate Collection qualifierUsers; // 2 Bean -> user1, user2@Bean@Qualifier // 进行逻辑分组public User user1() {User user = new User();user.setId(7L);return user;}@Bean@Qualifier // 进行逻辑分组public User user2() {User user = new User();user.setId(8L);return user;}public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(QualifierAnnotationDependencylrjectionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();QualifierAnnotationDependencylrjectionDemo demo = applicationContext.getBean(QualifierAnnotationDependencylrjectionDemo.class);System.out.println("demo.user: " + demo.user);System.out.println("demo.namedUser: " + demo.namedUser);System.out.println("demo.allUsers: " + demo.allUsers);System.out.println("demo.qualifierUsers: " + demo.qualifierUsers);// 关闭应用上下文applicationContext.close();}}// 运行结果
demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.namedUser: User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.allUsers: [User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}]
demo.qualifierUsers: [User{id=7, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}, User{id=8, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}]
自定义分组注解, UserGroup
UserGroup
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.annotation.Qualifier;import java.lang.annotation.*;/*** 用户组注解: 扩展 {@link Qualifier @Qualifier}** @author Zhang Xiao* @since*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Qualifier
public @interface UserGroup {
}
QualifierAnnotationDependencylrjectionDemo
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;import javax.jws.soap.SOAPBinding;
import java.util.Collection;/*** {@link Qualifier} 注解依赖注入** @author Zhang Xiao* @see Qualifier* @since*/
public class QualifierAnnotationDependencylrjectionDemo {@Autowiredprivate User user; // super user -> primary = true@Autowired@Qualifier("user")private User namedUser; // 指定 Bean 名称 或 ID@Autowired // 只会获取不带Qualifier的Beanprivate Collection allUsers; // 2 Bean -> super user, user@Autowired@Qualifier // 只会获取带Qualifier的Beanprivate Collection qualifierUsers; // 2 Bean -> user1, user2, user3, user4@Autowired@UserGroupprivate Collection userGroupUsers; // 2 Bean -> user3, user4@Bean@Qualifier // 进行逻辑分组public User user1() {return createUser(7L);}@Bean@Qualifier // 进行逻辑分组public User user2() {return createUser(8L);}@Bean@UserGroup // 进行逻辑分组public User user3() {return createUser(9L);}@Bean@UserGroup // 进行逻辑分组public User user4() {return createUser(10L);}public static User createUser(Long id) {User user = new User();user.setId(id);return user;}public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(QualifierAnnotationDependencylrjectionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();QualifierAnnotationDependencylrjectionDemo demo = applicationContext.getBean(QualifierAnnotationDependencylrjectionDemo.class);System.out.println("demo.user: " + demo.user);System.out.println("demo.namedUser: " + demo.namedUser);System.out.println("demo.allUsers: " + demo.allUsers);System.out.println("demo.qualifierUsers: " + demo.qualifierUsers);System.out.println("demo.userGroupUsers: " + demo.userGroupUsers);// 关闭应用上下文applicationContext.close();}}// 运行结果
demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.namedUser: User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.allUsers: [User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}]
demo.qualifierUsers: [User{id=7, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}, User{id=8, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}, User{id=9, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}, User{id=10, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}]
demo.userGroupUsers: [User{id=9, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}, User{id=10, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}]
基于注解 @Qualifier 扩展限定
自定义注解 - 如 Spring Cloud @LoadBalanced
使用 API ObjectFactory 延迟注入
使用 API ObjectProvider 延迟注入(推荐)
LazyAnnotationDependencyInjectionDemo
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;import javax.jws.soap.SOAPBinding;
import java.util.Collection;/*** {@link ObjectProvider} 实现延迟依赖注入** @author Zhang Xiao* @since*/
public class LazyAnnotationDependencyInjectionDemo {@Autowiredprivate User user; // 实时注入@Autowiredprivate ObjectProvider userObjectProvider; // 延迟注入@Autowiredprivate ObjectFactory> userObjectFactoryCollection; // 延迟注入public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(LazyAnnotationDependencyInjectionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();LazyAnnotationDependencyInjectionDemo demo = applicationContext.getBean(LazyAnnotationDependencyInjectionDemo.class);// 输出 super user --> primary = trueSystem.out.println("demo.user: " + demo.user);// 输出 super userSystem.out.println("demo.userObjectProvider: " + demo.userObjectProvider.getObject()); // ObjectProvider 继承 ObjectFactory// 输出 user, super userSystem.out.println("demo.userObjectFactory: " + demo.userObjectFactoryCollection.getObject());// 输出 user, super userdemo.userObjectProvider.forEach(System.out::println);// 关闭应用上下文applicationContext.close();}}// 运行结果
demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.userObjectProvider: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.userObjectFactory: [User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}]
User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
基础知识
入口 - DefaultListableBeanFactory#resolveDependency
AnnotationDependencyInjectionResolutionDemo 注入单个Bean
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;import java.util.Collection;/*** 注解驱动的依赖注入处理过程** @author Zhang Xiao* @since*/
public class AnnotationDependencyInjectionResolutionDemo {@Autowired // 依赖查找 (处理)private User user; // DependencyDescriptor ->// 必须 (required = true)// 实时注入 (eager = true)// 通过类型 (User.class)// 字段名称 ("user")// 是否首要 (primary = true)public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);// 输出 super user --> primary = trueSystem.out.println("demo.user: " + demo.user);// 关闭应用上下文applicationContext.close();}}
因为我们xml定义了user和super user 所以这里有两个名称
它会加入两次
找到了两个
所以说判断是否为primary其实就是用的BeanDefinition里面的元信息
注意: 这里拿到的super user是个class
AnnotationDependencyInjectionResolutionDemo 注入集合Bean
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;import java.util.Collection;
import java.util.Map;
import java.util.Optional;/*** 注解驱动的依赖注入处理过程** @author Zhang Xiao* @since*/
public class AnnotationDependencyInjectionResolutionDemo {@Autowired // 依赖查找 (处理)private User user; // DependencyDescriptor ->// 必须 (required = true)// 实时注入 (eager = true)// 通过类型 (User.class)// 字段名称 ("user")// 是否首要 (primary = true)@Autowiredprivate Map mapUser;public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);// 输出 super user --> primary = trueSystem.out.println("demo.user: " + demo.user);System.out.println("demo.mapUser: " + demo.mapUser);System.out.println("demo.optionalUser: " + demo.optionalUser.get());System.out.println("demo.lazyUser: " + demo.lazyUser);// 关闭应用上下文applicationContext.close();}}// 运行结果
demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.mapUser: {user=User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, superUser=SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}}
demo.optionalUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;import java.util.Collection;
import java.util.Map;
import java.util.Optional;/*** 注解驱动的依赖注入处理过程** @author Zhang Xiao* @since*/
public class AnnotationDependencyInjectionResolutionDemo {@Autowired // 依赖查找 (处理)private User user; // DependencyDescriptor ->// 必须 (required = true)// 实时注入 (eager = true)// 通过类型 (User.class)// 字段名称 ("user")// 是否首要 (primary = true)@Autowiredprivate Map mapUser;@Autowiredprivate Optional optionalUser;public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);// 输出 super user --> primary = trueSystem.out.println("demo.user: " + demo.user);System.out.println("demo.mapUser: " + demo.mapUser);System.out.println("demo.optionalUser: " + demo.optionalUser.get());System.out.println("demo.lazyUser: " + demo.lazyUser);// 关闭应用上下文applicationContext.close();}}// 运行结果
demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.mapUser: {user=User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, superUser=SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}}
其他同上唯一的就是这里事处理过个Bean
AnnotationDependencyInjectionResolutionDemo 注入Optional Bean
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;import java.util.Collection;
import java.util.Map;
import java.util.Optional;/*** 注解驱动的依赖注入处理过程** @author Zhang Xiao* @since*/
public class AnnotationDependencyInjectionResolutionDemo {@Autowired // 依赖查找 (处理)private User user; // DependencyDescriptor ->// 必须 (required = true)// 实时注入 (eager = true)// 通过类型 (User.class)// 字段名称 ("user")// 是否首要 (primary = true)@Autowiredprivate Map mapUser;@Autowiredprivate Optional optionalUser;public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);// 输出 super user --> primary = trueSystem.out.println("demo.user: " + demo.user);System.out.println("demo.mapUser: " + demo.mapUser);System.out.println("demo.optionalUser: " + demo.optionalUser.get());System.out.println("demo.lazyUser: " + demo.lazyUser);// 关闭应用上下文applicationContext.close();}}// 运行结果
demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.mapUser: {user=User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, superUser=SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}}
demo.optionalUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
AnnotationDependencyInjectionResolutionDemo 注入延迟 Bean
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;import java.util.Collection;
import java.util.Map;
import java.util.Optional;/*** 注解驱动的依赖注入处理过程** @author Zhang Xiao* @since*/
public class AnnotationDependencyInjectionResolutionDemo {@Autowired // 依赖查找 (处理)private User user; // DependencyDescriptor ->// 必须 (required = true)// 实时注入 (eager = true)// 通过类型 (User.class)// 字段名称 ("user")// 是否首要 (primary = true)@Autowiredprivate Map mapUser;@Autowiredprivate Optional optionalUser;@Autowired@Lazy // 延迟Beanprivate User lazyUser;public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);// 输出 super user --> primary = trueSystem.out.println("demo.user: " + demo.user);System.out.println("demo.mapUser: " + demo.mapUser);System.out.println("demo.optionalUser: " + demo.optionalUser.get());System.out.println("demo.lazyUser: " + demo.lazyUser);// 关闭应用上下文applicationContext.close();}}// 运行结果
demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.mapUser: {user=User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, superUser=SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}}
demo.optionalUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.lazyUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
依赖描述符 - DependencyDescriptor
declaringClass: 当前声明注入, 注入描述, 换而言之它是一个被注入的容器, 那么这个容器就称为声明的这个类
methodName: 方法名称可以为空, (方法注入)
parameterTypes: 方法参数, 构造器参数来操作(构造器注入)
parameterIndex: 参数索引它的顺序从0开始
fieldName: 字段名(字段注入)
required: 可以理解为Autowired注解里面的required
eager: 可以理解为Lazy注解里面的value
nestingLevel: 嵌套层次这里主要指的事@Autowired也有可能放在你的嵌套类里面去
containingClass: 包含类
resolvableType: 泛型类型
typeDescriptor: 类型描述
方法注入, 字段注入, 构造器注入, 是可选的如果三个都是空它就没没有注入的来源, 那这个显然是不对的
自定绑定候选对象处理器 - AutowireCandidateResolver
多个Bean是用的Set去重的方式, 所以是没有顺序可言的
总结
1、DefaultListableBeanFactory#resolveDependency 判断是否懒加载,懒加载直接返回CGLIB代理对象;
2、doResolveDependency 开始进行依赖注入;
3、resolveMultipleBeans 判断注入的对象是否是集合类型(Stream,Collection,Array,Map) ,是的话直接return ;
4、findAutowireCandidates 根据类型查找所有匹配到的bean,返回一个Map对象;
5、determineAutowireCandidate 选取唯一bean名称,如果有多个bean,即返回@Primary修饰的;
6、通过BeanFactory#getBean返回结果
@Autowired 注入规则
@Autowired 注入过程
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;import java.util.Collection;
import java.util.Map;
import java.util.Optional;/*** 注解驱动的依赖注入处理过程** @author Zhang Xiao* @since*/
@Configuration
public class AnnotationDependencyInjectionResolutionDemo {@Autowired // 依赖查找 (处理)private User user; // DependencyDescriptor ->// 必须 (required = true)// 实时注入 (eager = true)// 通过类型 (User.class)// 字段名称 ("user")// 是否首要 (primary = true)// @Autowired
// private Map mapUser;
//
// @Autowired
// private Optional optionalUser;
//
// @Autowired
// @Lazy // 延迟Bean
// private User lazyUser;public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);// 输出 super user --> primary = trueSystem.out.println("demo.user: " + demo.user);
// System.out.println("demo.mapUser: " + demo.mapUser);
// System.out.println("demo.optionalUser: " + demo.optionalUser.get());
// System.out.println("demo.lazyUser: " + demo.lazyUser);// 关闭应用上下文applicationContext.close();}}
注意: 有CommonAnnotationBeanPostProcessor它会先执行CommonAnnotationBeanPostProcessor, 后执行AutowiredAnnotationBeanPostProcessor, 通过这个applyMergedBeanDefinitionPostProcessors方法循环就能看出, 想调整顺序自己修改order值
剩下跟15一样过程了
总结:
先是找元信息然后进行注入:主要流程:AbstractAutowireCapableBeanFactory#createBean()-->doCreateBean()
1.调用applyMergedBeanDefinitionPostProcessors -> postProcessMergedBeanDefinition -> findAutowiringMetadata中找到该类中注解为Autowired、Value、Inject的字段、方法等
2.调用populateBean -> postProcessProperties,先调用findAutowiringMetadata找到待注入的元信息(比如user),然后调用metadata的inject方法,底层调用的是AutowiredFieldElement和AutowiredMethodElement的inject方法,
2.1 构造DependencyDescriptor(比如user)
2.2 调用beanFactory.resolveDependency获取待注入的bean(比如user),这里又是一轮的createBean(比如superUser不存在,则会创建)
2.3 获取后进行反射注入:field.set(bean, value)
15-16连体总结:
在 AbstractApplicationContext#refresh#finishBeanFactoryInitialization 方法中,初始化所有还未初始化的 Bean(不是抽象、单例模式、不是懒加载方式)通过 DefaultListableBeanFactory#preInstantiateSingletons 方法进行初始化,会通过 AbstractBeanFactory#getBean(beanName) 方法对每个 Bean 进行初始化Bean 初始化的过程比较繁琐,大致过程如下:1. 先找到对应的 BeanDefinition 对象,然后会走到 AbstractAutowireCapableBeanFactory#createBean 方法,**进行实例化**、**填充属性值**、调用 Bean 的**初始化方法**2. 在填充属性值的过程,默认根据类型进行注入,那么在 AbstractAutowireCapableBeanFactory#autowireByType 的方法中会调用 DefaultListableBeanFactory#resolveDependency 方法进行注入,最后还是会通过 AbstractBeanFactory#getBean(beanName) 方法获取到需要注入的 Bean 对象
3. 在填充属性值的时候也会通过 AutowiredAnnotationBeanPostProcessor 注入属性值,该注入增强器会对 @Autowired 或者 @Value 注解标注的属性进行注入,也是通过 DefaultListableBeanFactory#resolveDependency 方法进行注入。具体过程可看 AutowiredAnnotationBeanPostProcessor 的私有内部类 AutowiredFieldElement#inject 方法
@Inject 注入过程
如果 JSR-330 存在于 ClassPath 中,复用 AutowiredAnnotationBeanPostProcessor 实现
javax.inject javax.inject 1
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;import javax.inject.Inject;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;/*** 注解驱动的依赖注入处理过程** @author Zhang Xiao* @since*/
@Configuration
public class AnnotationDependencyInjectionResolutionDemo {@Autowired // 依赖查找 (处理)private User user; // DependencyDescriptor ->// 必须 (required = true)// 实时注入 (eager = true)// 通过类型 (User.class)// 字段名称 ("user")// 是否首要 (primary = true)// @Autowired
// private Map mapUser;
//
// @Autowired
// private Optional optionalUser;
//
// @Autowired
// @Lazy // 延迟Bean
// private User lazyUser;@Injectprivate User injectUser;public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);// 输出 super user --> primary = trueSystem.out.println("demo.user: " + demo.user);System.out.println("demo.injectUser: " + demo.injectUser);
// System.out.println("demo.mapUser: " + demo.mapUser);
// System.out.println("demo.optionalUser: " + demo.optionalUser.get());
// System.out.println("demo.lazyUser: " + demo.lazyUser);// 关闭应用上下文applicationContext.close();}}// 运行结果
demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.injectUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
实现原理跟15-16一样
遍历来查询装饰的注解, 注意它是有顺序的集合, 所以会根据添加的注解顺序来进行操作
CommonAnnotationBeanPostProcessor
其实CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor差不多, 只不过CommonAnnotationBeanPostProcessor多了一个生命周期, CommonAnnotationBeanPostProcessor倒数第4位, AutowiredAnnotationBeanPostProcessor倒数第三位, 所以CommonAnnotationBeanPostProcessor先执行后执行AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor倒数第4位, AutowiredAnnotationBeanPostProcessor倒数第三位, 所以CommonAnnotationBeanPostProcessor先执行后执行AutowiredAnnotationBeanPostProcessor
可以自定义order或者@Order
它多个用的LifecycleMetadata元信息
多了个初始化方法和销毁方法, 对应的就是PostConstruct/PreDestroy
找元信息
跟AutowiredAnnotationBeanPostProcessor那个查询一样, 主要看buildResourceMetadata
@Resource也是不能放在含static的字段/方法的, 递归去查找元信息
PostConstruct/PreDestroy在哪里执行的
它会去构建LifecycleElement的method方法, 所以生命周期的两个注解PostConstruct/PreDestroy只允许注入到方法上面
递归先父类,后子类的PostConstruct/PreDestroy
生命周期回调方法
基于 AutowiredAnnotationBeanPostProcessor 实现
package org.xiaoge.thinking.in.spring.ioc.dependency.injection.annotation;import org.springframework.beans.factory.annotation.Autowired;import java.lang.annotation.*;/*** 自定义注入使用(@Autowired 元注解)** @author Zhang Xiao* @since*/
@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Autowired
public @interface MyAutowired {/*** Declares whether the annotated dependency is required.* Defaults to {@code true}.*/boolean required() default true;}
package org.xiaoge.thinking.in.spring.ioc.dependency.injection.annotation;import java.lang.annotation.*;/*** 自定义依赖注入注解** @author Zhang Xiao* @since*/
@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InjectedUser {}
package org.xiaoge.thinking.in.spring.ioc.dependency.injection;import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.xiaoge.thinking.in.spring.ioc.dependency.injection.annotation.InjectedUser;
import org.xiaoge.thinking.in.spring.ioc.dependency.injection.annotation.MyAutowired;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;import javax.inject.Inject;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;import static org.springframework.context.annotation.AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME;/*** 注解驱动的依赖注入处理过程** @author Zhang Xiao* @since*/
public class AnnotationDependencyInjectionResolutionDemo {@Autowired // 依赖查找 (处理)private User user; // DependencyDescriptor ->// 必须 (required = true)// 实时注入 (eager = true)// 通过类型 (User.class)// 字段名称 ("user")// 是否首要 (primary = true)@Autowiredprivate Map mapUser;@Autowiredprivate Optional optionalUser;@Autowired@Lazy // 延迟Beanprivate User lazyUser;@Injectprivate User injectUser;@MyAutowiredprivate User myAutowiredUser;@InjectedUserprivate User injectedUser;/**** 核心是Bean名称是AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME, 因为它只会注入一次* 只注入我自己的注解, 其他注解全部失效, 想之前的也生效用setAutowiredAnnotationTypes吧其他注解也加载进来* @return*/
// @Bean(name = AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)
// public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {
// AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
// autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationType(InjectedUser.class);
// return autowiredAnnotationBeanPostProcessor;
// }/*** 兼容老的api, 新老都生效 让容器里面存在两个(AutowiredAnnotationBeanPostProcessor)* @return*/@Beanpublic static AutowiredAnnotationBeanPostProcessor beanPostProcessor2() {AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationType(InjectedUser.class);return autowiredAnnotationBeanPostProcessor;}/*** 无效* @return*/
// @Bean
// public AutowiredAnnotationBeanPostProcessor beanPostProcessor2() {
// AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
// autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationType(InjectedUser.class);
// return autowiredAnnotationBeanPostProcessor;
// }public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");// 启动应用上下文applicationContext.refresh();AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);// 输出 super user --> primary = trueSystem.out.println("demo.user: " + demo.user);System.out.println("demo.injectUser: " + demo.injectUser);System.out.println("demo.mapUser: " + demo.mapUser);System.out.println("demo.optionalUser: " + demo.optionalUser);System.out.println("demo.lazyUser: " + demo.lazyUser);System.out.println("demo.myAutowiredUser: " + demo.myAutowiredUser);// AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAMESystem.out.println("demo.injectedUser: " + demo.injectedUser);// AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME// 关闭应用上下文applicationContext.close();}}// 运行结果
demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.injectUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.mapUser: {user=User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, superUser=SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}}
demo.optionalUser: Optional[SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}]
demo.lazyUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.myAutowiredUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
demo.injectedUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}
就是因为它所以只有自定义注解生效了, 原有注解失效, 因为它只会注入一次, 而加了static的优先
总结:
上下文refresh后,会调用registerBeanPostProcessors注册各beanPostProcessors。此时demo所在的类并没有初始化为bean。
但是如果要拿到自定义的AutowiredAnnotationBeanPostProcessor,就必须拿到demo的bean后调用beanPostProcessor来拿到这个PostProcessor bean。这就必然导致整个demo配置类先实例化初始化,也就导致@InjectUser注入的bean还没有被AutowiredAnnotationBeanPostProcessor解析,就注入进来了,也就是null。如果加上static,那么就不需要先拿到demo的bean,可以直接调用类方法获取这个AutowiredAnnotationBeanPostProcessor。那么就会导致先拿到processor,后拿到demo的bean。这样demo在初始化的时候,就会正常解析自定义@InjectUser。所以对于同时存在bean的定义和bean的注入的配置类,顺序很容易弄错。
自定义实现