spring Boot----注解驱动开发

前提

  SSM框架,使用的是ClassPathXmlApplicationContext(IOC容器),一个加载配置文件

  spring Boot框架,启动加载的是AnnotationConfigApplicationContext(IOC容器),一个扫描注解


@ComponentScan

  扫描bean,SpringBootApplication里面有这个注解

  jdk1.8,可以多次使用@ComponentScan,jdk1.8之前,可以使用@ComponentScans,里面写多个@ComponentScan

@ComponentScan(
        value = {"com.xuecheng.api"},
        //排除Controller注解的类
        excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})},
        
        //includeFilters要和useDefaultFilters搭配,禁用默认filter
        includeFilters ={@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})},
        useDefaultFilters = false
)
  • FilterType.ASSIGNABLE_TYPE:给定类型,即使没有注解也可以加载到容器中,并且这个类的子类也会加载
  • FilterType.Custom:自定义规则,参数是给一个自定义的TypeFilter的实现类,如下
class TestFilter 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();

        if (classMetadata.getClassName()==""){
            return true;
        }
        return false;
    }
}


@ComponentScan(
        value = {"com.xuecheng.api"},
        //includeFilters要和useDefaultFilters搭配,禁用默认filter
        includeFilters ={@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {TestFilter.class})},
        useDefaultFilters = false
)

 

@Scope

@Configuration
class Config{
    
    /**
     *     ConfigurableBeanFactory#SCOPE_PROTOTYPE
     * 	 * @see ConfigurableBeanFactory#SCOPE_SINGLETON
     * 	    这两个一般不用,实际中,直接手动new对象,放到请求域中
     * 	 * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
     * 	 * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
     * 
     */
    @Scope("PROTOTYPE")
    @Bean
    public User user(){

    }
}

   

@Lazy

@Configuration
class Config{

    //只有单实例,才可以使用
    @Lazy
    @Bean
    public User user(){

    }
}

 

@Conditional

class testCondition implements Condition{
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        context.getBeanFactory();
        context.getClassLoader();
        context.getRegistry();
        context.getResourceLoader();

        String str = context.getEnvironment().getProperty("os.name");
        if ("Windows".contains(str)){
            return true;
        }
        return false;
    }
}
//必须满足这个条件,类中所有的bean,才能生效
@Conditional({testCondition.class})
@Configuration
class Config{
    
    //必须满足这个条件,当前bean,才能生效
    @Conditional({testCondition.class})
    @Bean
    public User user(){

    }
}

  

@Import

常规的导入bean方式:

  • ComponentScan+@component
  • @Configuration+@Bean
  • @Import【@Import,@ImportSelector,@ImportBeanDefinitionRegistrar】
  • spring提供的FactoryBean(工厂Bean)

使用方式1

  导入常规类

/**
 * 	 * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
 * 	 * or regular component classes to import (或者导入常规的类,组件名:全限定类名)
 */
@Import({User.class})
@Configuration
class Config{
}

使用方式2

  导入@ImportSelector

/**
 * 自定义逻辑需要导入的组件
 */
class ImportSelectorTest implements ImportSelector{

    /**
     * 
     * @param importingClassMetadata:当前标注@Import注解的类的 所有的注解
     * @return
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //可以获取除了当前标注@Import注解的类的 其他所有的注解
        //importingClassMetadata
        importingClassMetadata.getAnnotationTypes();
        //需要返回需要导入组件的全类名数组
        return new String[]{"com.zy.User"};
    }
}

@Import({ImportSelectorTest.class})
@Configuration
class Config{
}

使用方式3

class ImportBeanDefinitionRegistrarTest implements ImportBeanDefinitionRegistrar{
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(User.class);
        registry.registerBeanDefinition("user",rootBeanDefinition);
    }
}

@Import({ImportBeanDefinitionRegistrarTest.class})
@Configuration
class Config{
}

 

FactoryBean

class FactoryBeanTest implements FactoryBean{

    //返回要给对象,这个对象会添加到容器中
    @Override
    public Object getObject() throws Exception {
        User user = new User();
        return user;
    }

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

    @Override
    public boolean isSingleton() {
        return true;
    }
}


@Configuration
class Config{
    @Bean
    public FactoryBeanTest factoryBeanTest(){
        //FactoryBean
        return new FactoryBeanTest();
    }
    public static void  main(){
        //当容器获取bean的时候,获取的是FactoryBeanTest.getObject()返回的对象
        Object b = applicationContext.getBean("FactoryBeanTest");

        //此时获取的是FactoryBeanTest本身了
        //BeanFactory.FACTORY_BEAN_PREFIX=&
        Object b = applicationContext.getBean("&FactoryBeanTest");
    }
}

  

 

posted @ 2021-01-11 15:45  小名的同学  阅读(138)  评论(0编辑  收藏  举报