spring注解方式向IOC容器中注册组件

前言:为了简化开发的步骤和降低设计的耦合性,在spring框架中引入了IOC容器这一概念。IOC理论提出的观点大体是这样的:借助于"第三方"实现具有依赖关系的对象之间的解耦。因此,在spring中,对象的创建与赋值均借助于IOC容器由框架来实现。初始化时,我们将组件放置与IOC容器中儿不具体指定使用该组件的对象,当某一具体对象需要使用组件时,直接从容器中获取即可。


目录:

一、通过@Bean方式添加

通常会通过在配置类中方法上添加@bean将对象注册到容器中。在spring整合其他框架场景中,为了降低模块之间的耦合性,需要考虑使用工厂bean来添加组件
1.1 @bean添加组件
示例1:将person实例化并注册到容器中,最后在测试类中从容器中取出person对象。
I) 创建实体类Person.java
package com.allin.pojo;

public class Person {
    private String userName;

    private Integer age;

    private String sex;

    public Person(String userName, Integer age, String sex) {
        this.userName = userName;
        this.age = age;
        this.sex = sex;
    }
    
    public String getUserName(){
        return userName;
    }

    @Override
    public String toString() {
        return "Person{" +
                "userName='" + userName + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }
}
II) 创建配置类MyConfig,在类上使用@Configuration注解标注为配置类,在类中方法上使用@bean注解将对象注册到容器中。

默认注册到容器中的组件名为注册组件时方法名,可通过@bean(value=“XXX”)修改组件名

package com.allin.config;

import com.allin.pojo.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfig {

    @Bean
    public Person person(){
        return new Person("miaowu",22,"male");
    }
}
III) 创建测试类,在测试类中根据组件名将对象从IOC容器中取出
    @Test
    public void test02(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        String[] definitionNames = applicationContext.getBeanDefinitionNames();
        //查询容器中有哪些组件
        for(String name : definitionNames){
            System.out.println(name);
        }
        Person person = (Person) applicationContext.getBean("person");
        System.out.println(person.getUserName());
    }
IV) 测试结果:容器中包含MyConfig和person组件,将person对象按组件名取出并打印person对象中属性值

请添加图片描述

1.2 使用工厂bean添加组件
当项目中存在多个相同类型实体类,我们不需要将所有实体类实例化并注册到容器中,可以使用工厂bean进行动态选择项目所需要的实体类进行初始化并注册到容器中,以提高项目运行的效率和提高程序设计的灵活性
示例2:项目中包含有多种颜色的实体类(Blue,Yellow),选择Blue实体类进行实例化并注册到容器中,测试类将对象取出并进行测试。
I) 创建实体类Blue和Yellow

entity:Blue:

package com.allin.pojo;

public class Blue {

    public String description = "this is blue color";

}

entity:Yellow:

package com.allin.pojo;

public class Yellow {

    private String discription = "this is yellow color";

}
II) 创建工厂bean类ColorFactoryBean实现FactoryBean,getObject类返回Blue对象
package com.allin.pojo;

import org.springframework.beans.factory.FactoryBean;

public class ColorFactoryBean implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        return new Blue();
    }

    @Override
    public Class<?> getObjectType() {
        return Blue.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}
III) 创建配置类MyConfig02注册工厂bean
package com.allin.config;

import com.allin.pojo.ColorFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfig02 {

    @Bean
    public ColorFactoryBean colorFactoryBean(){
        return new ColorFactoryBean();
    }
}
IV) 创建测试类
    @Test
    public void test06(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig02.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(String name : beanDefinitionNames){
            System.out.println(name);
        }
        //工厂bean获取的是调用getObject创建的对象
        Object bean = applicationContext.getBean("colorFactoryBean");
        System.out.println("bean的类型:" + bean.getClass());

        Blue bean1 = (Blue) applicationContext.getBean("colorFactoryBean");
        System.out.println(bean1.description);
    }
v) 测试结果:将colorFactoryBean对象注册入容器中,实际存储在IOC容器中的为以colorFactory为组件名的,由ColorFactory类中getObject()方法实例化的Blue对象

在这里插入图片描述

二、通过包扫描方式添加

spring中定义了 @Component、@Service、@Controller、@Repository注释来声明组件,通过在配置类中使用包扫描@ComponentScan将组件添加到容器中
示例3:创建实体类User,包含uesrName和password属性,使用@Component注解标注;创建应用类Service,定义add方法,使用@Service标注。在配置类Config01类中将组件注册到容器中,在测试类中将组件从容器中取出进行测试
I) 创建实体类User,使用@Component注解标注
package com.allin.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class User {

    @Value("miaowu")
    private String userName;

    @Value("5201024")
    private String password;

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}
II) 创建应用类MyService,使用@Service标注注解
package com.allin.service;


import org.springframework.stereotype.Service;

@Service
public class MyService {

    public void add(){
        System.out.println("service……add……execute!");
    }
}
III) 创建配置类MyConfig01,使用包扫描将被@Component、@Service注解标注的类注册到容器中。

被标注的类以类名为组件名被注册到容器中

package com.allin.config;


import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(value = {"com.allin.pojo", "com.allin.service"})
public class MyConfig01 {
}
IV) 创建测试类,将组件从容器中取出并进行测试
    @Test
    public void test05(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig01.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(String name : beanDefinitionNames){
            System.out.println(name);
        }
        User user = (User)applicationContext.getBean("user");
        System.out.println(user);
        MyService service = (MyService) applicationContext.getBean("myService");
        service.add();
    }
V) 测试结果:User、MyService类以类名为组件名注册到容器中

在这里插入图片描述

三、通过@Import方式添加

使用@Import方式可以方便注册第三方包到容器中

示例4:将User类通过@Import注册到容器中,User类中包含内容同上示例3
I) 创建实体类User,同上示例3
II) 在配置类Config03上使用@Import导入User类

使用@Import注册的组件名为全类名

package com.allin.config;

import com.allin.pojo.User;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(User.class)
public class MyConfig03 {
}
III) 创建测试类将组件取出
    @Test
    public void test07(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig03.class);
        User bean = (User)applicationContext.getBean("com.allin.pojo.User");
        System.out.println(bean);
    }
IV) 测试结果:@Import将实体类以全类名为组件名注册到组件中

在这里插入图片描述


3.1 ImportSelector接口
ImportSelector接口中含有两个方法:

String[] selectImports(AnnotationMetadata importingClassMetadata);

  • 返回值:导入到容器中的组件全类名
  • AnnotationMetadata:当前标注@Import注解的类的所有注释信息

default Predicate getExclusionFilter();

相当于给selectImports返回的String加一个过滤器,如果Predicate返回为True,则过滤,不进行注册

示例5:将示例2中的Yellow、Blue通过ImportSelector接口导入到容器中,通过getExclusionFilter()过滤掉Blue对象
I) 创建Yellow、Blue对象,同上示例2
II) 实现ImportSelector接口,在selectImports方法将要导入的组件全类名返回,在getExclusionFilter()方法中过滤全类名中含有Blue的组件
package com.allin.importselector;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

import java.util.function.Predicate;

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com/allin/pojo/Blue","com/allin/pojo/Yellow"};
    }

    @Override
    public Predicate<String> getExclusionFilter() {
        return className->className.contains("Blue");
    }
}
III) 创建配置类ImportSelectorConfig,将MyImportSelector接口导入
package com.allin.config;

import com.allin.importselector.MyImportSelector;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Import(MyImportSelector.class)
@Configuration
public class ImportSelectorConfig {
}
IV) 创建测试类,测试容器中包含哪些组件
    @Test
    public void test08(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ImportSelectorConfig.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(String beanName : beanDefinitionNames){
            System.out.println("beanName:" + beanName + "===" + "bean对象:" + applicationContext.getBean(beanName));
        }
    }
V) 测试结果:容器中包含Yellow组件,不含Blue组件

在这里插入图片描述

3.2 ImportBeanDefinitionRegistrar接口
ImportBeanDefinitionRegistrar支持我们自己写的代码封装成 BeanDefinition对象;实现此接口的类会回调 postProcessBeanDefinitionRegistry方法注册到spring容器中
实例6:將Blue实体类通过ImportBeanDefinitionRegistrar注册到容器中
I) 创建实体类Blue,Bean类中内容同上示例2
II) 创建MyImportBeanDefinitionRegistrar实现ImportBeanDefinitionRegistrar接口,在registerBeanDefinitions方法中自定义组件名,并将Blue实体类转为组件注册到容器中
package com.allin.registor;

import com.allin.pojo.Blue;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean definition = registry.containsBeanDefinition("red");
        if(!definition){
            RootBeanDefinition beanDefinition = new RootBeanDefinition(Blue.class);
            registry.registerBeanDefinition("Blue",beanDefinition);
        }
    }
}
III) 创建配置类将ImportBeanDefinitionRegistrar接口导入
package com.allin.config;

import com.allin.registor.MyImportBeanDefinitionRegistrar;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(MyImportBeanDefinitionRegistrar.class)
public class MyConfig04 {
}
IV) 创建测试类,查看Blue组件是否注册到容器中
    @Test
    public void test09(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig04.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(String name : beanDefinitionNames){
            System.out.println(name);
        }
    }
V) 测试结果:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring IOC容器Spring框架的核心部分之一,它负责管理和组织应用程序的各种组件IOC是控制反转的意思,它实现了依赖注入(DI)的思想。DI是指通过容器来管理和注入组件的依赖关系,而不是手动在代码创建和管理这些组件。当应用程序需要使用某个组件时,可以直接向IOC容器索取该组件,而不需要自己手动创建或管理。 在SpringIOC容器负责管理和组织各种Bean。Bean是Spring的基本组件,它可以是任何一个Java对象。IOC容器会根据配置文件或注解来实例化、配置和管理这些Bean。它会在应用程序启动时,根据配置文件或注解的定义,创建并初始化所有的Bean,并将它们存储在容器。当应用程序需要使用某个Bean时,只需向IOC容器索取即可。 Spring提供了多种IOC容器的实现,包括XML配置的ApplicationContext和基于注解的AnnotationConfigApplicationContext等。这些容器提供了丰富的功能,如依赖注入、AOP、事务管理等。通过使用IOC容器,可以实现松耦合、可扩展和可测试的应用程序。引用<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [SpringIOC容器详解,通俗易懂看这一篇就够了](https://blog.csdn.net/qq_45369589/article/details/123095028)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [详解Spring IOC 容器启动流程分析](https://download.csdn.net/download/weixin_38750209/12747162)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值