Spring-IOC组件注册

IOC_组件注册的几种方法

前置测试用例

//a.自定义注册类MySpringIocConfig
//注解配置类
@Configuration
public class MySpringIocConfig{

}

//b.通过 new AnnotationCofigApplicationContext(MySpringIocConfig.class)获取配置类之注册的组件
//获取Spring上下文ApplicationContext,全文中获取注册的bean
public class IocTest{
    @Test
    public void test(){
    //获取上下文
    AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(MySpringIocConfig.class);
    //获取全文注册的组件的名称
    String[] strs=applicationContext.getBeanDefinitionNames();
    }
}

@ComponentScan
-配置类上使用

普通使用

多用于自编写类的组件的注册,例如扫描dao和service包下的使用了@Component等注解的类,注册到容器中。

  1. 将要给IOC容器管理的bean的类上,添加注解[@Service@Component@Repository@Controller]
  2. 在配置类上,添加注解@ComponentScan(value={"com.gh.dao","com.gh.service"})
@Configuration
@ComponentScan(value={"com.gh.service","com.gh.dao"})
public class MySpringIocConfig{
}

高级使用

@ComponentScan 注解配置FilterType过滤器,过滤掉一些bean使其不注册

自定义TypeFilter对组件进行过滤

//使用FilterType,过滤注册的组件
//编写配置类,加上@ComponentScan注解
//includeFilters =>只包含,配合UseDefaultFilters=false
//excludeFilters =>不包含,配置FilterType
@Configuration
@ComponentScan(
    value={"com.gh"},
    includeFilters={
        @ComponentScan.Filter(type=FilterType.ANNOTATION,value=Component.class),
        @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,value = Apple.class),
        @ComponentScan.Filter(type = FilterType.CUSTOM,value = MyTypeFilter.class)
    },
    useDefaultFilters = false
)
public class MySpringIocConfig{

}

//编写TypeFilter实现类,内部编写过滤逻辑
public class MyTypeFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //获取注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //获取环境信息
        Resource resource = metadataReader.getResource();
        //返回true,则通过过滤;
        return false;
    }
}

spring提供的Filter组件过滤器

//① 只包含的Filters,userDefaulters=false
@ComponentScan(
    value={"com.gh"},
    includeFilters={
    @ComponentScan.Filter(type=Filter.ANNOTATION,value=Component.class),
    @ComponentScan.Filter(type=FIlter.CUATOM,value=MyTypeFilter.class),
    @ComponentScan.FIlter(type=Filter.ASSIGNABLE,value=Person.class)
    },
    userDefaultFilter=false
)

//②不包含
@ComponentScan(
    value={"com.gh"},
    excludeFilters={
    @ComponentScan.Filter(type=Filter.ANNOTATION,value=Component.class),
    @ComponentScan.Filter(type=FIlter.CUATOM,value=MyTypeFilter.class),
    @ComponentScan.FIlter(type=Filter.ASSIGNABLE,value=Person.class)
    },
    userDefaultFilter=false
)

//其中FilterType是一个枚举类型,有5个类型

@Bean
-配置类内的方法上使用

普通用法

第三方的组件包,我们无法入侵代码,在类上加注解;使用在配置类中配置第三方bean,以让IOC容器管理第三方bean

  1. 编写配置类MySpringIocConfig
  2. 在配置类中,添加方法且方法上添加@Bean注解
@Configuration
public class MySpringIocCOnfig{
    //可以通过applicationContext.getBean("person"),获取该注册的组件
    @Bean
    public Person person(){
        retrun new Person("张三");
    }

    //可以通过applicationContext.getBean("person1"),获取该注册的组件
    @Bean
    public Person person1(){
        return new Person("李四");
    }

    //可以通过applicationContext.getBean("personY"),获取该注册的组件
    @Bean("personY")
    public Person personX(){
        return new Person("王五");
    }

    //配置组件的作用范围
    //singleton 单例(默认值)-每次容器获取的都是同一个对象
    //prototype 多例-每次容器获取组件,都init一个新的对象
    //request web中-每次一个新的请求,注册一次组件
    //session web中-每次一个新的session,init一个新的组件
    @Bean
    @Scope("prototype")
    public Apple apple(){
        return new Apple();
    }

    // 每次获取IOC容器获取orange组件时,采取注册bean;在IOC容器初始化时,不注册bean;
    @Bean
    @Lazy
    public Orange orange(){
        return new Orange();
    }
}

高级用法

注册实现了FactoryBean接口的工厂bean

// 编写工程类,实现FactoryBean接口
public class AppleFactoryBean implements FactoryBean<Apple> {
    @Override
    public Apple getObject() throws Exception {
        return new Apple();
    }

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

    @Override
    public boolean isSingleton() {
        return true;
    }
}
//配置类中注册AppleFactoryBean
@Configuration
public class MySpringIocCofig{

    @Bean
    public AppleFactoryBean appleFactoryBean(){
        return new AppleFactoryBean();
    }
}

//获取注册的组件
public class MainTest{
    @Test
    public void test(){
    AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(MySpringIocConfig.class);
    //获取工厂类注册的bean =>返回的时apple
    applicationContext.getBean("appleFactoryBean");
    //获取工厂类本身 =>返回的是appleFactoryBean
    applicationContext.getBean("&appleFactoryBean");
    }
}

@Import
-配置类上使用

直接导入类或者自定义类的导入规则类

编写配置类,添加 @Import
注解

//配置类
@Configuration
@Import({Color.class,Orange.class})
public class MySpringIocConfig(){

}

//可以通过全类名获取组件
public class MainTest{
    @Test
    public void test(){
    AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(MySpringIocConfig.class);
    applicationContext.getBean("com.gh.pojo.Color");
    }
}

编写实现了 ImportSelector
接口的实现类

//配置类
@Configuration
@Import({MyImportSelector.class})
public class MySpringIocConfig(){

}

//实现了ImportSelector接口的实现类,返回一个String[],内的string要写全类名
public class MyImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.gh.pojo.Fruit","cpm.gh.pojo.Apple"};
    }
}

//可以通过全类名获取组件
public class MainTest{
    @Test
    public void test(){
    AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(MySpringIocConfig.class);
    applicationContext.getBean("com.gh.pojo.Fruit");
    }
}

编写实现了 ImportBeanDefinitionRegistry
接口的实现类

//编写配置类
@Configuration
@Import({MyImportBeabDefinitionRegistry.class})
public class MySpringIocConfig{
}
//实现ImportBeanDefinitionRegistry的实现类
public class MyImportBeanDefinitionRegistry implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    RootBeanDefinition beanDefinition = new RootBeanDefinition(Apple.class);
    registry.registerBeanDefinition("golphin",beanDefinition);
    }
}
//通过golphin获取组件
public class MainTest{
    @Test
    public void test(){
    AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicatinContext(MySpringIocCOnfig.class);
    application.getBean("golphin");//获取到了apple组件
}
}

@Conditional
按照条件配置bean

@Conditional 可以放在方法上,也可以放在类上

@Conditional value中的class是=>实现了Condition接口的实现类

放在配置类注册bean的方法上时 => bean注册时,若能满足条件,才能够从IOC容器中获取;

放在配置类打上方时 => 配置类下注册的bean,要满足条件才能够获取到;

//操作系统时Windows
public class ConditionWindows implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String osName=context.getEnvironment().getProperty("os.name");
        if(osName.toLowerCase().contains("windows")){
        return true;
        }
        return false;
    }
}
//操作系统时Linux
public class ConditionLinux implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String osName=context.getEnvironment().getProperty("os.name");
        if(osName.toLowerCase().contains("linux")){
        return true;
    }
    return false;
    }
}

//编写配置类
@Configuration
@ComponentScan({"com.gh"})
@Conditional(ConditionWindows.class)
public class MySpringIocConfig{
    @Bean
    public Apple apple(){
        return new Apple();
    }


    @Bean
    @Conditonal(ConditionLinux.class)
    public Orange orange(){
        return new Orange();
    }
}

原文 

https://segmentfault.com/a/1190000020631888

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » Spring-IOC组件注册

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址