spring组件注册

一  给容器中注册bean

1、新建一个类,并在类上加上注解@Configuration,表明这是一个配置类。

1 @Configuration
2 public class MainConfig {
3 
4 }

 2、然后在配置类中添加一个带返回值的方法,并加上@Bean,表明注册该bean实例

    @Bean()
    public Person getPerson() {
        Person person = new Person("张三", 22);
        return person;
    }

3、最后新建一个测试类,用AnnotationConfigApplicationContext(Class<?>... annotatedClasses)构造方法启动spring容器,就能得到配置类下的所有bean实例

public class MainTest {
    
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        Person person =(Person) context.getBean(Person.class);
        System.out.println(JSON.toJSONString(person));
        
        
        String[] beanName = context.getBeanNamesForType(Person.class);
        System.out.println(Arrays.toString(beanName));
    }

}

这样一个bean就注册好了

注意:@Bean默认生成的bean的id是方法名,如果想要自定义bean的id,可以写为@Bean("placeholder"),这样就可以设置该bean的id

 

二  启动注解扫描

1、在@Configuration的类下添加@ComponentScan即可启动注解扫描。

2、@ComponentScan的用法为:

    String[] value() default {}  //扫描指定包下的注解

    Filter[] excludeFilters() default {}  //排除Filter指定的过滤规则

    Filter[] includeFilters() default {}  //只包含Filter指定的过滤规则,注意:使用includeFilters必须还得加上useDefaultFilters=false才能生效

    boolean useDefaultFilters() default true  //是否使用默认过滤规则,只有设置为false,includeFilters才会生效

3、@Filter的用法为:

    FilterType type() default FilterType.ANNOTATION

      /*FilterType 枚举类型,包含:

      *  ANNOTATION   //按照注解过滤

      *  ASSIGNABLE_TYPE  //按照给定的类过滤

      *  ASPECTJ  //按照ASPECTJ表达式过滤,不常用

      *  REGEX  //按照正则表达式过滤

      *  CUSTOM  //使用自定义规则过滤,使用这种过滤规则,Classes必须包含自定义的实现了 org.springframework.core.type.filter.TypeFilter 的类

      */

    @AliasFor("value") Class<?>[] classes() default {};  //指定要过滤的类

    String[] pattern() default {};  //指定要过滤的表达式语句

    

4、示例:

  @ComponentScan(value="com.dj", excludeFilters= {

    @Filter(type=FilterType.ANNOTATION,classes= {Controller.class})

  })  //指定扫描com.dj下的注解,但排除@Controller注解

  @ComponentScan(value="com.dj", includeFilters= {
    @Filter(type=FilterType.ANNOTATION,classes= {Controller.class})
  }, useDefaultFilters=false)  //指定扫描com.dj下的注解,但只扫描@Controller注解

5、还可以用 @ComponentScans(value= { }) 设置多个ComponentScan

注意:@ComponentScan不会对@Configuration指定的类和类中的方法生效

三  自定义过滤规则

1、使用自定义过滤规则,Filter必须设置成 @Filter(type=FilterType.CUSTOM, classes= {MyTypeFilter.class}) ,其中 MyTypeFilter 是实现了 org.springframework.core.type.filter.TypeFilter的类

2、示例:

  @ComponentScan(value="com.dj", includeFilters= {

    @Filter(type=FilterType.CUSTOM, classes= {MyTypeFilter.class})
  }  //指定扫描com.dj下的注解,过滤规则为 MyTypeFilter 指定的过滤规则

3、MyTypeFilter写法为:

public class MyTypeFilter implements TypeFilter{

    /**
     *  设置匹配规则:过滤掉类名不包含"er"的类
     * metadataReader:读取当前类的信息
     * metadataReaderFactory:可以获取任何类的信息
     * return true:表示不过滤此类
     *           false:表示过滤此类
     */
    @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();
        System.out.println("----->"+className);
        if(className.contains("er")) {
            return true;
        }
        return false;
    }

}

 四  @Scope设置bean的作用域

1、用法:@Scope("placeholder") ,其中placeholder可以设置成:

    prototype  //基于原型创建,多实例,IOC容器并不会创建方法创建对象放在容器中,只有在每次调用时才会创建

    singleton  //基于单例创建,单实例(默认值),IOC容器会调用方法创建对象放到IOC容器中,以后每次调用直接从容器中获取

    request  //同一个请求创建一个实例,不常用

    session  //同一个session创建一个实例,不常用

五  @Lazy设置bean的懒加载

1、单实例默认在容器启动是创建bean,@Lazy只针对单实例的bean,可以设置单实例在容器启动是不创建,在第一次使用时才创建,

 用法:

   @Lazy

六  @Conditional,按照条件给容器注册bean

1、@Conditional可以加到任何bean(无论类还是方法)上,只有条件成立时才创建bean,用法: 

  @Conditional({MyCondition.class})  // MyCondition 必须是实现 org.springframework.context.annotation.Condition 的类

2、示例:

    @Conditional({MyCondition.class})
    @Bean("testPerson")
    public Person getPerson00() {
        Person person = new Person("testEnvironment", 22);
        System.out.println(JSON.toJSON(person));
        return person;
    }

3、MyCondition示例:

public class MyCondition implements Condition{

    /**
     *  条件为os为Windows是返回true
     * @param context : 判断条件能够使用的上下文
     * @param metadata: \@Conditional的注解信息
     * @return true: 条件成立,创建bean
     *            false: 条件不成立,不创建bean
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //获取IOC使用的beanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //获取类加载器
        ClassLoader classLoader = context.getClassLoader();
        //获取环境信息
        Environment environment = context.getEnvironment();
        //获取bean定义的注册类
        BeanDefinitionRegistry registry = context.getRegistry();
        
        String osName = environment.getProperty("os.name");
        if(osName.toLowerCase().contains("windows")) {
            return true;
        }
        return false;
    }

}

 六  @Import 快速导入组件

1、@Import 用于快速导入组件,用于被@Configuration标注的配置类上

2、用法:

  @Import({Placeholder.class,...})  //创建指定类的bean,默认bean的id为类的全类名(包名+类名)

七  ImportSelector 导入组件

1、ImportSelector是一个接口,所有实现 ImportSelector 的类只要放入 @Import 中spring就会自动创建 selectImports 方法返回的全类名的bean

2、@Import示例:

  @Import({MyImportSelector.class})   // MyImportSelector 实现了 ImportSelector 接口

3、MyImportSelector 示例:

public class MyImportSelector implements ImportSelector{

    /**
     * spring会根据返回的全类名信息创建bean
     * importingClassMetadata: 当前标注@import类的所有注解信息
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        
        //注意return一定不要返回null,否则会报错,可以返回一个空数组
        return new String[] {"com.dj.entity.Blue","com.dj.entity.Red"};
    }

}

注意:selectImports 方法一定不要返回null,否则会报空指针异常,可以返回一个空数组

八  ImportBeanDefinitionRegistrar 注册bean

1、ImportBeanDefinitionRegistrar 是一个接口,所有实现 ImportBeanDefinitionRegistrar 的类只要放入 @Import 中spring就会自动执行 registerBeanDefinitions方法自动注册bean

2、@Import示例:

  @Import({MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})  // MyImportSelector 实现了 ImportSelector 接口,MyImportBeanDefinitionRegistrar 实现了 ImportBeanDefinitionRegistrar 接口

3、MyImportBeanDefinitionRegistrar示例:

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{

    /**
     *  手工注册bean
     * AnnotationMetadata: 当前类的注解信息
     * BeanDefinitionRegistry: BeanDefinition注册类,
     *         把所有需要添加到容器中的bean,调用BeanDefinitionRegistry.registerBeanDefinition手工注册进来
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //判断是否包含这个bean
        boolean containsRed = registry.containsBeanDefinition("com.dj.entity.Red");
        System.out.println("sssssssssssssssssssssssssssss");
        if(containsRed) {
            
            //指定bean的定义信息(bean的类型,scope,lazy等)
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Rainbow.class);
            rootBeanDefinition.setScope("singleton");
            //手工注册bean并且自定义bean的id
            registry.registerBeanDefinition("rainbow", rootBeanDefinition);
        }
    }

}

九  使用FactoryBean注册bean

1、FactoryBean是一个接口,实现factoryBean的类在创建返回值为FactoryBean的bean时,通过id获取到的bean不是FactoryBean本身,而是调用FactoryBean.getObject()创建的bean

  只有通过 &+id 获取到的bean才是FactoryBean本身

2、示例:

public class YellowFactoryBean implements FactoryBean<Yellow>{

    @Override
    public Yellow getObject() throws Exception {
        return new Yellow();
    }

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

    /*
     * return:true  代表创建一个单实例的bean
     *           false  代表创建一个多实例的bean,每一次使用都会调用getObject()重新生成一个bean
     */
    @Override
    public boolean isSingleton() {
        return true;
    }

}

3、创建返回值为FactoryBean的bean

    @Bean
    public YellowFactoryBean getYellowFactoryBean() {
        return new YellowFactoryBean();
    }

4、创建单元测试

    @Test
    public void FactoryBeanTest() {
        AnnotationConfigApplicationContext application = new AnnotationConfigApplicationContext(MainConfig.class);
        //getBean入伙直接通过id拿到的是一个FactoryBean,会默认拿到FactoryBean调用getObject()创建的bean,不是FactoryBean本身
        Object object0 = application.getBean("getYellowFactoryBean");
        System.out.println(object0.getClass().getName());
        //只有通过&+id拿到的FactoryBean,才能拿到FactoryBean本身
        Object object1 = application.getBean("&getYellowFactoryBean");
        System.out.println(object1.getClass().getName());    
    }

猜你喜欢

转载自www.cnblogs.com/programmlover/p/10127080.html