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

1 包扫描+组件标注注解

1.1 简单使用

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

1.2 ConponentScan自定义扫描规则

  • 创建MyComponentScanTypeFilter并实现TypeFilter
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;
        }
    }
}

  • 测试
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
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;
    }
}
  • 可以在方法上使用也可以在类上使用
@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
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中使用
@Configuration
@Import({Color.class, Red.class,MyImportSelector.class})
public class MainConfig2 {}

3.3 使用ImportBeanDefinitionRegistrar自定义注入Bean

  • 新建MyImportBeanDefinitionRegistrar并实现ImportBeanDefinitionRegistrar
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);
        }
    }
}
  • 使用
@Configuration
@Import({Color.class, Red.class, MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {}

4 使用FactoryBean<T>注入组件

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

//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {
    // 返回一个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注入
@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());
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逻辑峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值