Spring中给容器中注册组件的4种方式

简介: Spring中给容器中注册组件的4种方式

@[TOC]

1 包扫描+组件标注注解

1.1 简单使用

  • @ComponentScan注解
    @ComponentScan("com.yunfeng.spring2")
    public class MainConfig {
         
    }
    
  • 在自己创建的类上加@Controller@Service@Repository@Component注解
    @Controller
    public class BookController {
         
    }
    

    1.2 ConponentScan自定义扫描规则

  • 创建MyComponentScanTypeFilter并实现TypeFilter
    ```java
    package com.yunfeng.spring2.config;

import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;

/**

  • 自定义ComponentScan扫描规则
    */
    public class MyComponentScanTypeFilter implements TypeFilter {

    /*

    • @param metadataReader 读取当前扫描类的信息
    • @param metadataReaderFactory 读取其他任何类的信息
    • @return
    • @throws IOException
      */
      @Override
      public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
      //获取当前正在扫描类的注解信息
      AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
      //获取当前正在扫描类的类信息
      ClassMetadata classMetadata = metadataReader.getClassMetadata();
      //获取当前类资源(类路径)
      Resource resource = metadataReader.getResource();
      //获取类名
      String className = classMetadata.getClassName();
      if (className.contains("mapper")) {
       //true 代表匹配
       return true;
      
      }else {
       //false 代表不匹配
       return false;
      
      }
      }
      }
* 测试
```java
package com.yunfeng.spring2.config;

import com.yunfeng.spring2.entity.Person;
//import com.yunfeng.spring2.mapper.BookMapper;
import org.springframework.context.annotation.*;
//import org.springframework.stereotype.Controller;
//import org.springframework.stereotype.Repository;
//import org.springframework.stereotype.Service;

@Configuration
//@ComponentScan(value = "com.yunfeng.spring2",includeFilters = {
//        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class})
//},useDefaultFilters = false)
@ComponentScans(value = {
        @ComponentScan(value = "com.yunfeng.spring2",includeFilters = {
                //注解类型过滤
//                @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class}),
                //类类型过滤
//                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {BookMapper.class}),
                //自定义过滤
                @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyComponentScanTypeFilter.class})
        },useDefaultFilters = false)
})
public class MainConfig {

    @Bean(value = "person")
    public Person addPerson(){
        return new Person("胡思源",16);
    }
}

2 @Bean导入的第三方包里面的组件

2.1 简单使用

@ComponentScan(value = "com.yunfeng.spring2")
public class MainConfig {
   

    @Bean(value = "person")
    public Person addPerson(){
   
        return new Person("胡思源",16);
    }
}

2.2 自定义条件注入

  • 新建WindowsCondition并实现Condition
    ```java
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.env.Environment;
    import org.springframework.core.type.AnnotatedTypeMetadata;

public class WindowsCondition implements Condition {

/**
 *
 * @param context 判断条件能使用的上下文(环境)
 * @param annotatedTypeMetadata 注释信息
 * @return
 */
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata annotatedTypeMetadata) {
    //1、能获取到IOC使用的beanfactory(创建对象并装配的工厂)
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    //2、获取类加载器
    ClassLoader classLoader = context.getClassLoader();
    //3、获取当前环境信息
    Environment environment = context.getEnvironment();
    //4、获取到bean定义的注册类
    BeanDefinitionRegistry registry = context.getRegistry();
    String property = environment.getProperty("os.name");
    if (property.contains("Windows")){
        return true;
    }
    return false;
}

}

* 可以在方法上使用也可以在类上使用
```java
@Conditional(WindowsCondition.class)
    @Bean(value = "bill")
    public Person addPerson1(){
        return new Person("bill",76);
    }
  • 测试
    @Test
      public void test03(){
         
          Environment environment = context.getEnvironment();
          System.out.println(environment.getProperty("os.name"));
          Map<String, Person> persons = context.getBeansOfType(Person.class);
          System.out.println("persons = " + persons);
      }
    

    3 @Import快速给容器中导入一个组件

    3.1 @Import直接导入

    @Configuration
    @Import({
         Color.class, Red.class})
    public class MainConfig2 {
         
    }
    

    3.2 使用ImportSelector返回需要导入的组件的全类名数组

  • 新建MyImportSelector 并实现ImportSelector
    ```java
    import org.springframework.context.annotation.ImportSelector;
    import org.springframework.core.type.AnnotationMetadata;

// 自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {

/**
 * 自定义逻辑返回需要导入的组件
 * @param annotationMetadata 当前标注@Import注解的类的所有注解信息
 * @return 返回值,就是导入到容器中的组件全类名
 */
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {

// annotationMetadata.
return new String[]{"com.yunfeng.spring2.config.Blue","com.yunfeng.spring2.config.Yellow"};
}
}

* 在`@Import`中使用
```java
@Configuration
@Import({Color.class, Red.class,MyImportSelector.class})
public class MainConfig2 {}

3.3 使用ImportBeanDefinitionRegistrar自定义注入Bean

  • 新建MyImportBeanDefinitionRegistrar并实现ImportBeanDefinitionRegistrar
    ```java
    import com.yunfeng.spring2.entity.RainBow;
    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 {
/*

 * @param annotationMetadata 当前类的注解信息
 * @param registry BeanDefinition注册类:
 *                               调用BeanDefinitionRegistry.registerBeanDefinition手工注册类进来
 */
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
    boolean definition1 = registry.containsBeanDefinition("com.yunfeng.spring2.entity.Red");
    boolean definition2 = registry.containsBeanDefinition("com.yunfeng.spring2.entity.Blue");
    if (definition1 && definition2){
        //指定bean定义信息
        RootBeanDefinition definition = new RootBeanDefinition(RainBow.class);
        //设置非单例
        definition.setScope("prototype");
        //注册一个Bean,指定bean名
        registry.registerBeanDefinition("RainBow",definition);
    }
}

}

* 使用
```java
@Configuration
@Import({Color.class, Red.class, MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {}

4 使用FactoryBean<T>注入组件

  • 创建ColorFactoryBean并实现FactoryBean<Color>
    ```java
    import org.springframework.beans.factory.FactoryBean;

//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean {
// 返回一个Color对象,这个对象会添加到容器中
@Override
public Color getObject() throws Exception {
return new Color();
}

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

//true为单实例
@Override
public boolean isSingleton() {
    return true;
}

}

* 使用`@Bean`注入
```java
@Bean
    public ColorFactoryBean colorFactoryBean(){
        return new ColorFactoryBean();
    }
  • 测试
    @Test
      public void test04(){
         
          String[] names = context.getBeanDefinitionNames();
          for (String name : names) {
         
              System.out.println(name);
          }
          //从工厂中获取的是getObject创建的对象
          Object colorFactoryBean = context.getBean("colorFactoryBean");
          System.out.println(colorFactoryBean.getClass());
          //获取工厂Bean本身
          Object colorFactoryBean2 = context.getBean("&colorFactoryBean");
          System.out.println(colorFactoryBean2.getClass());
      }
    
目录
相关文章
|
19天前
|
Java 应用服务中间件 Nacos
Spring Cloud 常用各个组件详解及实现原理(附加源码+实现逻辑图)
Spring Cloud 常用各个组件详解及实现原理(附加源码+实现逻辑图)
31 0
|
12天前
|
Java 测试技术 开发者
Spring IoC容器通过依赖注入机制实现控制反转
【4月更文挑战第30天】Spring IoC容器通过依赖注入机制实现控制反转
22 0
|
12天前
|
XML Java 程序员
什么是Spring的IoC容器?
【4月更文挑战第30天】什么是Spring的IoC容器?
20 0
|
18天前
|
XML Java 数据格式
【spring】01 Spring容器研究
【spring】01 Spring容器研究
9 0
|
23天前
|
Java Maven Nacos
Spring Cloud Eureka 服务注册和服务发现超详细(附加--源码实现案例--及实现逻辑图)
Spring Cloud Eureka 服务注册和服务发现超详细(附加--源码实现案例--及实现逻辑图)
31 0
|
1月前
|
前端开发 Java 容器
家族传承:Spring MVC中父子容器的搭建与管理指南
家族传承:Spring MVC中父子容器的搭建与管理指南
26 3
|
1月前
|
XML Java 数据格式
无需手动注册:精通Spring注解扫描的高效利用
无需手动注册:精通Spring注解扫描的高效利用
23 2
|
2月前
|
SpringCloudAlibaba 负载均衡 Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(三)Eureka服务注册中心
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(三)Eureka服务注册中心
49 1
|
4天前
|
监控 Kubernetes Docker
【Docker 专栏】Docker 容器内应用的健康检查与自动恢复
【5月更文挑战第9天】本文探讨了Docker容器中应用的健康检查与自动恢复,强调其对应用稳定性和系统性能的重要性。健康检查包括进程、端口和应用特定检查,而自动恢复则涉及重启容器和重新部署。Docker原生及第三方工具(如Kubernetes)提供了相关功能。配置检查需考虑检查频率、应用特性和监控告警。案例分析展示了实际操作,未来发展趋势将趋向更智能和高效的检查恢复机制。
【Docker 专栏】Docker 容器内应用的健康检查与自动恢复
|
18小时前
|
存储 安全 开发者
如何删除 Docker 镜像、容器和卷?
【5月更文挑战第11天】
7 2
如何删除 Docker 镜像、容器和卷?