Spring编程思想之依赖注入

依赖注入类型 配置元数据举例

  • 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包.类#成员 标签}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容