Spring注解驱动-自动装配(四)

自动装配:Spring的依赖注入,对IOC容器中各个组件的依赖关系进行赋值。

创建MainConfigOfAutowired.java配置类。使用@ComponentScan指定扫描的controller、service、dao。

1.@Autowired&@Qualifier&@Primary

在Controller、Service、Dao这种结构中,经常使用到@Autowired注解,完成自动注入。

@Autowired默认有限按照类型从容器中查找组件,相当于getBean(Class<T> requiredType)方式从容器中获取组件。如果找到多个相同类型的组件,再按照名称作为组件id去容器中查找,相当于getBean(String name)方式从容器中获取组件。

使用@Qualifier注解可以明确指定我们需要装配的组件id,@Qualifier是根据名称来查找的。

使用@Autowired注解标记的属性,默认情况下,是必须装配到容器中的,如果在装配过程中报错,程序就无法运行,如果我们希望,即使装配不成功也可以不报错,可以给@Autowired指定一个required属性,并设置其值为false既可。

@Primary注解:当自动注入的时候,找到了多个同类型的组件,优先使用哪一个进行注入。

2.@Resource&@Inject

@Resource和@Autowired一样,都可以完成自动装配,@Autowired是属于Spring的注解,@Resource是属于JSR250的注解。@Resource默认按照组件的名称进行装配,也可以添加属性来自定义name的值。@Resource不支持@Primary,也不支持required=false属性。

@Inject属于JSR330的注解,需要导入javax.inject的依赖才能使用。它是支持@Autowired的特性,也就是支持@Primary。

@Resource和@Inject是Java规范定义的,@Autowired是Spring规范定义的,如果项目使用的框架不支持@Autowired,那么只能使用@Resource和@Inject了。

3.方法、构造器位置的自动装配

@Autowired注解支持的地方有:构造器,方法,参数,属性。

当@Autowired注解标注在方法上时,Spring容器创建当前对象的时候,就会调用这个方法。方法中如果有参数,会尝试从容器中获取。

当@Autowired注解标注在构造器上时,Spring容器创建当前对象的时候,会调用有参构造器,参数从容器中获取,如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略。

当@Autowired注解标注在参数上时,表示参数要从容器中获取,该方法也会被执行。

@Bean标注的方法用来创建对象的时候,如果有参数,参数也是从容器中获取的,此时的@Autowired也可以省略。

4.Aware注入Spring底层组件&原理

自定义组件如果想要使用Spring底层容器的组件(ApplicationContext,BeanFactory等),自定义组件需要实现xxxAware接口,在创建对象的时候,调用接口规定的方法注入相关组件。

package com.atguigu.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.stereotype.Component;
import org.springframework.util.StringValueResolver;

@Component
public class MyAware implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
    // 实现BeanNameAware接口,可以获取到当前bean的名字
    public void setBeanName(String s) {
        System.out.println("当前bean的名字是:" + s);
    }

    // 实现ApplicationContextAware可以获取到当前的IOC容器
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("当前的IOC容器是:"+ applicationContext);
    }

    // 实现EmbeddedValueResolverAware可以使用stringValueResolver做字符串的解析
    public void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {
        System.out.println(stringValueResolver.resolveStringValue("我的操作系统是${os.name},1+1=#{1+1}"));
    }
}

这些xxxAware是通过xxxAwareProcessor来做的处理,参考后置处理器。

查看ApplicationContextAwareProcessor类的postProcessBeforeInitialization()方法,再查看invokeAwareInterfaces()方法,在invokeAwareInterfaces()方法中,判断当前类实现了哪个接口,将需要的内容设置进去。

5.@Profile环境搭建

Profile是Spring为我们提供的一种根据当前环境,动态切换和激活组件的功能。常见的就是:开发环境,测试环境,生产环境。

创建MainConfigOfProfile.java主配置类,在类中通过@Bean加入几个组件,这里,我加入Dog,Cat,Car用于测试,分别代表不同环境下需要注入的组件。

6.@Profile根据环境注册bean

在@Bean上添加@Profile环境标识,只有当这个环境被激活的时候,这个组件才会被加入到容器中,它的默认值是default。@Profile不仅可以标在组件上,还可以标在配置类上,只有是指定环境,整个配置类才能生效。没有标记@Profile的组件,不受环境变化的影响,都会注入容器。

激活环境的方法:

  1. 在VM options里加入-Dspring.profiles.active=cat,表示当前生效的环境是cat环境,标记了@Profile({"cat"})注解的组件就可以被注入容器中了。
  2. 使用代码设置激活环境(见下面的代码)。
package com.atguigu;

import com.atguigu.config.MainConfigOfProfile;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ProfileTest {
    @Test
    public void test() {
        // 使用代码方式设置要激活的环境,需要调用AnnotationConfigApplicationContext的无参构造器
        // 对比参考有参构造:AnnotationConfigApplicationContext(MainConfigOfProfile.class),多了一步setActiveProfiles()方法
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
        // 设置需要激活的环境
        annotationConfigApplicationContext.getEnvironment().setActiveProfiles("dog");
        // 调用register注册主配置类
        annotationConfigApplicationContext.register(MainConfigOfProfile.class);
        // 手动刷新容器
        annotationConfigApplicationContext.refresh();
        String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
        for (String name : beanDefinitionNames) {
            System.out.println("容器中添加的组件:" + name);
        }
        annotationConfigApplicationContext.close();
    }
}

7.IOC-小结

在组件添加中,@Conditional和@Import比较重要,在Spring Boot中使用频繁。

在组件赋值中,需要掌握@Value和@PropertySource注解。

在组件注入中,方法写的参数,构造器中的参数,都会从容器中获取,以及xxxAware注入Spring底层组件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值