04.Spring Framework 之组件注入

1. @Autowired & @Qualifier & @Primary

1.1 @Autowired

1.1.1 使用方式

@Autowired:自动注入,如果没有就会报错,可以指定 required=false 避免报错

  • 默认优先按照类型去容器中找对应的组件:applicationContext.getBean(Xxx.class),找到就赋值,如果找到多个相同类型的组件,再将属性的名称作为组件的 id 去容器中查找:applicationContext.getBean("xxx")

  • 标注在构造器上:如果组件只有一个有参构造器,这个有参构造器的 @Autowired 可以省略,参数位置的组件是从容器中获取的

  • 标注在方法位置:@Autowired 可以使用在 setter 方法上,Spring 容器创建当前对象时会自动调用方法完成赋值,方法使用的自定义类型参数的值从 IOC 容器中获取

  • 标注在参数上:@Bean 注解标注方法中的参数会从容器中获取,此时的 @Autowired 可以省略

1.1.2 环境搭建

代码已经上传至 https://github.com/masteryourself-tutorial/tutorial-spring ,详见 tutorial-spring-framework/tutorial-spring-framework-injection/tutorial-spring-framework-injection-autowired 工程

1. PersonController
@Controller
@ToString
public class PersonController {

    @Autowired
    private PersonService personService2;

}
2. StudentController
@Data
public class StudentController {

    private PersonService personService;

    /**
     * 只要一个有参的构造参数
     *
     * @param personService
     */
    public StudentController(PersonService personService) {
        this.personService = personService;
    }

}
3. TeacherController
@Controller
@ToString
public class TeacherController {

    private PersonService personService;

    /*@Autowired*/
    public TeacherController(/*@Autowired*/ PersonService personService2) {
        this.personService = personService2;
    }
}
4. UserController
@Controller
@ToString
public class UserController {

    private PersonService personService;

    @Autowired
    public void setPersonService(PersonService personService1) {
        this.personService = personService1;
    }
}
5. SpringConfig
@Configuration
@ComponentScan("pers.masteryourself.tutorial.spring.framework.injection")
public class SpringConfig {

    @Bean
    public PersonService personService1() {
        return new PersonService("1");
    }

    @Bean
    public PersonService personService2() {
        return new PersonService("2");
    }

    @Bean
    public StudentController studentController(/*@Autowired*/ PersonService personService1){
        return new StudentController(personService1);
    }

}
6. AutowiredApplication
public class AutowiredApplication {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        PersonController personController = context.getBean(PersonController.class);
        // PersonController(personService2=PersonService(label=2))
        System.out.println(personController);
        UserController userController = context.getBean(UserController.class);
        // UserController(personService=PersonService(label=1))
        System.out.println(userController);
        TeacherController teacherController = context.getBean(TeacherController.class);
        // TeacherController(personService=PersonService(label=2))
        System.out.println(teacherController);
        StudentController studentController = context.getBean(StudentController.class);
        // StudentController(personService=PersonService(label=1))
        System.out.println(studentController);
    }

}

1.2 @Qualifier

1.2.1 使用方式

使用 @Qualifier 指定需要装配的组件的 id,而不是使用属性名

1.2.2 环境搭建

代码已经上传至 https://github.com/masteryourself-tutorial/tutorial-spring ,详见 tutorial-spring-framework/tutorial-spring-framework-injection/tutorial-spring-framework-injection-qualifier 工程

1. PersonController
@ToString
@Component
public class PersonController {

    @Autowired
    @Qualifier("personService1")
    private PersonService personService2;

}

1.3 @Primary

1.3.1 使用方式

让 Spring 进行自动装配的时候,默认使用首选的 bean;也可以强制使用 @Qualifier 明确指定需要装配的 bean 的名字

1.3.2 环境搭建

代码已经上传至 https://github.com/masteryourself-tutorial/tutorial-spring ,详见 tutorial-spring-framework/tutorial-spring-framework-injection/tutorial-spring-framework-injection-primary 工程

1. SpringConfig
@Configuration
@ComponentScan("pers.masteryourself.tutorial.spring.framework.injection")
public class SpringConfig {

    @Bean
    @Primary
    public PersonService personService1() {
        return new PersonService("1");
    }

    @Bean
    public PersonService personService2() {
        return new PersonService("2");
    }

}

2. @Resource & @Inject

2.1 @Resource

@Resource 是 java 规范定义的注解,可以和 @Autowired 一样实现自动装配功能,默认是按照组件名称进行装配的

不支持 @Primary 功能,不支持 @Autowired(reqiured=false)

2.2 @Inject

需要导入 javax.inject 的包,和 Autowired 的功能一样,但没有 required=false 的功能

3. Aware

3.1 使用方式

自定义组件实现 xxxAware;在创建对象的时候,会调用接口规定的方法注入相关组件

3.2 环境搭建

代码已经上传至 https://github.com/masteryourself-tutorial/tutorial-spring ,详见 tutorial-spring-framework/tutorial-spring-framework-injection/tutorial-spring-framework-injection-aware 工程

1. MyAware
@Component
public class MyAware implements ApplicationEventPublisherAware, BeanFactoryAware, EnvironmentAware,
        EmbeddedValueResolverAware, BeanNameAware, ApplicationContextAware, ImportAware {

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println(String.format("{%s} ==========================>>>>>>>>>>>>>>>>>>>>>>>>>>>", "setBeanFactory"));
        System.out.println(beanFactory.getBean("myAware"));
    }

    @Override
    public void setBeanName(String beanName) {
        System.out.println(String.format("{%s} ==========================>>>>>>>>>>>>>>>>>>>>>>>>>>>", "setBeanName"));
        System.out.println("beanName is:" + beanName);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println(String.format("{%s} ==========================>>>>>>>>>>>>>>>>>>>>>>>>>>>", "setApplicationContext"));
        System.out.println("applicationContext 是否属于 AnnotationConfigApplicationContext:" +
                (applicationContext instanceof AnnotationConfigApplicationContext));
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        System.out.println(String.format("{%s} ==========================>>>>>>>>>>>>>>>>>>>>>>>>>>>", "setApplicationEventPublisher"));
        System.out.println("applicationEventPublisher is:" + applicationEventPublisher);
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        System.out.println(String.format("{%s} ==========================>>>>>>>>>>>>>>>>>>>>>>>>>>>", "setEmbeddedValueResolver"));
        System.out.println(resolver.resolveStringValue("my os is [${os.name}]"));
    }

    @Override
    public void setEnvironment(Environment environment) {
        System.out.println(String.format("{%s} ==========================>>>>>>>>>>>>>>>>>>>>>>>>>>>", "setEnvironment"));
        System.out.println("当前 encoding:" + environment.getProperty("file.encoding"));
    }

    @Override
    public void setImportMetadata(AnnotationMetadata annotationMetadata) {
        System.out.println(String.format("{%s} ==========================>>>>>>>>>>>>>>>>>>>>>>>>>>>", "setImportMetadata"));
        Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(Import.class.getName());
        System.out.println("获取注解信息:" + attributes);
    }
}

4. @Profile

4.1 使用方式

@Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件

加了环境标识的 bean,只有这个环境被激活的时候才能注册到容器中。默认是 default 环境

写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效

没有标注环境标识的 bean 在任何环境下都是加载的

4.2 环境搭建

代码已经上传至 https://github.com/masteryourself-tutorial/tutorial-spring ,详见 tutorial-spring-framework/tutorial-spring-framework-injection/tutorial-spring-framework-injection-profile 工程

1. SpringConfig
@Configuration
public class SpringConfig {

    @Profile("default")
    @Bean
    public Datasource localDatasource(){
        return new Datasource("local");
    }

    @Profile("dev")
    @Bean
    public Datasource devDatasource(){
        return new Datasource("dev");
    }

    @Profile("test")
    @Bean
    public Datasource testDatasource(){
        return new Datasource("test");
    }

    @Profile("prod")
    @Bean
    public Datasource prodDatasource(){
        return new Datasource("prod");
    }

}

4.3 激活

1. 通过启动参数激活

通过在 VM options 中配置启动参数 -Dspring.profiles.active=dev,test

2. 通过代码激活
public static void main(String[] args) {
    // 1. 创建一个 AnnotationConfigApplicationContext
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    // 2. 设置需要激活的环境
    context.getEnvironment().setActiveProfiles("dev", "test");
    // 3. 注册主配置类
    context.register(SpringConfig.class);
    // 4. 刷新容器
    context.refresh();
    String[] names = context.getBeanNamesForType(Datasource.class);
    for (String name : names) {
        // devDatasource
        // testDatasource
        System.out.println(name);
    }
}
发布了37 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/masteryourself/article/details/96782356