依赖注入类型 配置元数据举例
- Setter 方法
<proeprty name=” user” ref=” userBean” /> - 构造器
<constructor-arg name="user" ref="userBean" /> - 字段
@Autowired User user; - 方法
@Autowired public void user(User user) { ... } - 接口回调
class MyBean implements BeanFactoryAware { ... }
@Autowired
- 会自动忽略静态字段AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
ReflectionUtils.doWithLocalFields(targetClass, field -> {
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
- 实现类AutowiredAnnotationBeanPostProcessor
一注入类型
1.1Setter注入
1.1.1手动注入:
• XML 资源配置元信息
<bean class="org.geekbang.thinking.in.spring.ioc.dependency.injection.UserHolder">
<property name="user" ref="superUser" />
</bean>
• Java 注解配置元信息
• API 配置元信息
/**
* 为 {@link UserHolder} 生成 {@link BeanDefinition}
*
* @return
*/
private static BeanDefinition createUserHolderBeanDefinition() {
BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);
definitionBuilder.addPropertyReference("user", "superUser");
return definitionBuilder.getBeanDefinition();
}
1.1.2自动注入
- byName
- byType
<bean class="org.geekbang.thinking.in.spring.ioc.dependency.injection.UserHolder"
autowire="byType"
>
1.2构造器注入
1.2.1 手动模式
• XML 资源配置元信息
<bean class="org.geekbang.thinking.in.spring.ioc.dependency.injection.UserHolder">
<constructor-arg name="user" ref="superUser" />
</bean>
• Java 注解配置元信息
@Bean
public UserHolder userHolder(User user) {
return new UserHolder(user);
}
• API 配置元信息
/**
* 为 {@link UserHolder} 生成 {@link BeanDefinition}
*
* @return
*/
private static BeanDefinition createUserHolderBeanDefinition() {
BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);
definitionBuilder.addConstructorArgReference("superUser");
return definitionBuilder.getBeanDefinition();
}
构造器注入先于属性注入 会被属性注入覆盖
1.2.2 自动模式
- constructor
<bean class="org.geekbang.thinking.in.spring.ioc.dependency.injection.UserHolder"
autowire="constructor">
<!-- <property name="user" ref="superUser" /> 替换成 autowiring 模式 -->
</bean>
1.3 字段注入
1.3.1
Java 注解配置元信息
• @Autowired
• @Resource
• @Inject( 可选)
1.4方法注入
Java 注解配置元信息
• @Autowired
• @Resource
• @Inject( 可选)
• @Bean
public class AnnotationDependencyMethodInjectionDemo {
private UserHolder userHolder;
private UserHolder userHolder2;
private UserHolder userHolder3;
@Autowired
public void init1(UserHolder userHolder) {
this.userHolder = userHolder;
}
@Resource
public void init2(UserHolder userHolder2) {
this.userHolder2 = userHolder2;
}
@Resource
public void init3(UserHolder userHolder3) {
this.userHolder3 = userHolder3;
}
@Bean
public UserHolder userHolder(User user) {
return new UserHolder(user);
}
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类) -> Spring Bean
applicationContext.register(AnnotationDependencyMethodInjectionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载 XML 资源,解析并且生成 BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 依赖查找 AnnotationDependencyFieldInjectionDemo Bean
AnnotationDependencyMethodInjectionDemo demo = applicationContext.getBean(AnnotationDependencyMethodInjectionDemo.class);
// @Autowired 字段关联
UserHolder userHolder = demo.userHolder;
System.out.println(userHolder);
System.out.println(demo.userHolder2);
System.out.println(userHolder == demo.userHolder2);
System.out.println(userHolder==demo.userHolder3);
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
}
1.5接口回调注入
- BeanFactoryAware
获取 IoC 容器 - BeanFactory - ApplicationContextAware
获取 Spring 应用上下文 - ApplicationContext 对象 - EnvironmentAware
获取 Environment 对象 - ResourceLoaderAware
获取资源加载器 对象 - ResourceLoader - BeanClassLoaderAware
获取加载当前 Bean Class 的 ClassLoader - BeanNameAware
获取当前 Bean 的名称
1.6依赖注入类型的选择
• 低依赖: 构造器注入
• 多依赖: Setter 方法注入
• 便利性: 字段注入
• 声明类: 方法注入
二基础类型的注入、集合类型的注入
• 原生类型( 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 等
• 集合类型
数组类型( Array) : 原生类型、 标量类型、 常规类型、 Spring 类型
集合类型( Collection)
Collection: List、 Set( SortedSet、 NavigableSet、 EnumSet)
Map: Properties
<bean id="user" class="org.geekbang.thinking.in.spring.ioc.overview.domain.User">
<property name="id" value="1"/>
<property name="name" value="小马哥"/>
<property name="city" value="HANGZHOU"/>
<property name="workCities" value="BEIJING,HANGZHOU"/>
<property name="lifeCities">
<list>
<value>BEIJING</value>
<value>SHANGHAI</value>
</list>
</property>
<property name="configFileLocation" value="classpath:/META-INF/user-config.properties"/>
</bean>
三 限定类型的注入
@Qualifier 和@AutoWired
使用注解 @Qualifier 限定
• 通过 Bean 名称限定
• 通过分组限定
• 基于注解 @Qualifier 扩展限定
• 自定义注解 - 如 Spring Cloud @LoadBalanced
/**
* 用户组注解,扩展 {@link Qualifier @Qualifier}
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @since
*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Qualifier
public @interface UserGroup {
}
四延迟依赖注入
使用 API ObjectFactory 延迟注入
• 单一类型
• 集合类型
• 使用 API ObjectProvider 延迟注入( 推荐)
• 单一类型
• 集合类型
/**
* {@link ObjectProvider} 实现延迟依赖注入
* @see Qualifier
* @see Autowired
*
* @since
*/
@Configuration
public class LazyAnnotationDependencyInjectionDemo {
@Autowired
@Qualifier("user")
private User user; // 实时注入
@Autowired
private ObjectProvider<User> userObjectProvider; // 延迟注入
@Autowired
private ObjectFactory<Set<User>> usersObjectFactory;
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类) -> Spring Bean
applicationContext.register(LazyAnnotationDependencyInjectionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载 XML 资源,解析并且生成 BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 依赖查找 QualifierAnnotationDependencyInjectionDemo Bean
LazyAnnotationDependencyInjectionDemo demo = applicationContext.getBean(LazyAnnotationDependencyInjectionDemo.class);
// 期待输出 superUser Bean
System.out.println("demo.user = " + demo.user);
// 期待输出 superUser Bean
System.out.println("demo.userObjectProvider = " + demo.userObjectProvider.getObject()); // 继承 ObjectFactory
// 期待输出 superUser user Beans
System.out.println("demo.usersObjectFactory = " + demo.usersObjectFactory.getObject());
demo.userObjectProvider.forEach(System.out::println);
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
}
五依赖处理过程
基础知识
• 入口 - DefaultListableBeanFactory#resolveDependency
• 依赖描述符 - DependencyDescriptor
public class DependencyDescriptor extends InjectionPoint implements Serializable {
/**
* example
*
* class AnnotationDependencyMethodInjectionDemo{
* // 字段注入
* @Autowired
* private UserHolder userHolder2;
* //方法注入
* @Autowired
* public void init1(UserHolder userHolder) {
* this.userHolder = userHolder;
* }
* // 参数注入
* public void init4(@Autowired UserHolder userHolder) {
* this.userHolder = userHolder;
* }
* }
*/
/**
* 需要注入的类
* declaringClass =AnnotationDependencyMethodInjectionDemo.class
*/
private final Class<?> declaringClass;
/**
* 方法注入 methodName=init1
*/
@Nullable
private String methodName;
//参数注入 parameterTypes=UserHolder.class
@Nullable
private Class<?>[] parameterTypes;
private int parameterIndex;
// 字段注入 fieldName=userHolder2
@Nullable
private String fieldName;
/**
* @Autowired boolean required() default true; 注入类型是否必须存在
*/
private final boolean required;
/**
* 是否是lazy
*/
private final boolean eager;
/**
* 嵌套层次
*/
private int nestingLevel = 1;
/**
*包含类
*/
@Nullable
private Class<?> containingClass;
/**
* 泛型处理
*/
@Nullable
private transient volatile ResolvableType resolvableType;
/**
* 类型描述
*/
@Nullable
private transient volatile TypeDescriptor typeDescriptor;
• 自定绑定候选对象处理器 - AutowireCandidateResolver
DebugDemo
断点DefaultListableBeanFactory#resolveDependency
/**
* 注解驱动的依赖注入处理过程
*
*
* @see Qualifier
* @since
*/
@Configuration
public class AnnotationDependencyInjectionResolutionDemo {
// DependencyDescriptor ->
// 必须(required=true)
// 实时注入(eager=true)
// 通过类型(User.class)
// 字段名称("user")
// 是否首要(primary = true)
@Autowired // 依赖查找(处理)
private User user;
@Autowired
private ObjectFactory<User> objectFactory;
@Autowired // 集合类型依赖注入
private Map<String, User> users; // user superUser
@MyAutowired
private Optional<User> userOptional; // superUser
@Inject
private User injectedUser;
@Autowired // 依赖查找(处理)
@Lazy
private User lazyUser;
@InjectedUser
private User myInjectedUser;
// @Bean(name = AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)
// public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {
// AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
// // @Autowired + @Inject + 新注解 @InjectedUser
// Set<Class<? extends Annotation>> autowiredAnnotationTypes =
// new LinkedHashSet<>(asList(Autowired.class, Inject.class, InjectedUser.class));
// beanPostProcessor.setAutowiredAnnotationTypes(autowiredAnnotationTypes);
// return beanPostProcessor;
// }
@Bean
@Order(Ordered.LOWEST_PRECEDENCE - 3)
@Scope
public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {
AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
beanPostProcessor.setAutowiredAnnotationType(InjectedUser.class);
return beanPostProcessor;
}
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类) -> Spring Bean
applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载 XML 资源,解析并且生成 BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 依赖查找 QualifierAnnotationDependencyInjectionDemo Bean
AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);
// 期待输出 superUser Bean
System.out.println("demo.user = " + demo.user);
System.out.println("demo.injectedUser = " + demo.injectedUser);
// 期待输出 user superUser
System.out.println("demo.users = " + demo.users);
// 期待输出 superUser Bean
System.out.println("demo.userOptional = " + demo.userOptional);
// 期待输出 superUser Bean
System.out.println("demo.myInjectedUser = " + demo.myInjectedUser);
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
}
七 @Autowired 注入
@Autowired 注入规则
• 非静态字段
• 非静态方法
• 构造器
@Autowired 注入过程
• 元信息解析
AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
• 依赖查找
• 依赖注入( 字段、 方法)
AutowiredAnnotationBeanPostProcessor#postProcessProperties
AutowiredAnnotationBeanPostProcessor参考
八 @Inject 注入
AutowiredAnnotationBeanPostProcessor支持javax.inject.Inject Autowired Value
public AutowiredAnnotationBeanPostProcessor() {
// 设置@Autowired注解类型
this.autowiredAnnotationTypes.add(Autowired.class);
// 设置@Value注解类型
this.autowiredAnnotationTypes.add(Value.class);
try {
// 支持使用JSR330中的@Inject进行注入.
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 Injected javax.inject.Inject 这个是查找顺序
* @param
* @return
*/
@Nullable
private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
if (ao.getAnnotations().length > 0) { // autowiring annotations have to be local
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
if (attributes != null) {
return attributes;
}
}
}
return null;
}
九 Java通用注解注入原理
CommonAnnotationBeanPostProcessor
• 注入注解
• javax.xml.ws.WebServiceRef
• javax.ejb.EJB
• javax.annotation.Resource
• 生命周期注解
• javax.annotation.PostConstruct
• javax.annotation.PreDestroy
扩展
javadoc 常用
@see 引用
{@link包.类#成员 标签}