首页 > 编程语言 > 详细

Spring基于注解配置(四)

时间:2020-06-02 19:35:10      阅读:54      评论:0      收藏:0      [点我收藏+]

组件注册

1.@Configuration

通过@Configuration标识,告诉Spring这是一个配置类.

@Configuration    //告诉spring这是一个配置类
public class MainConf {

    
}

2.@ComponentScan

@ComponentScan这个注解通过value属性扫描所有被@Component,@Service,@Controller和@Repository标注过的类,将类放入IOC容器中

@ComponentScan可以通过includeFilters属性扫描的时候按照一定的规则排除组件;

@ComponentScan(value="com.spring",includeFilters= {
        @Filter(type=FilterType.ANNOTATION,classes= {Controller.class,Service.class}),
        @Filter(type=FilterType.ASSIGNABLE_TYPE,classes= {Service.class}),
        @Filter(type=FilterType.CUSTOM,classes= {MyTypeFilter.class})
},useDefaultFilters=false)

其中:

  1.ANNOTATION:按照注解进行排除

  2.ASSIGNABLE_TYPE:按照给定的类型进行排除

  3.ASPECTJ:使用ASPECTJ表达式进行排除

  4.REGEX:使用正则表达式进行排除

  5.CUSTOM:自定义规则

自定义规则需要实现TypeFilter接口

public class MyTypeFilter implements TypeFilter{

    /**
     * metadataReader,读取到当前正在扫描的类信息
     * metadataReaderFactory,可以获取到其他任何类信息的
     * 
     */
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
            throws IOException {
        //获取当前类注解的信息
        AnnotationMetadata metadata = 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;
    }
    
}

3.@Bean

@Bean可以将组件注册到IOC容器中

public class MainConf {

    @Bean //注册一个bean;类型就是返回值的类型id默认方法名作为id
    public Person person() {
        return new Person("lisi", 20);
    }
    
}

Person类:

public class Person {
    
    private String name;
    
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

    public Person(String name, Integer age) {
        super();
        this.name = name;
        this.age = age;
    }

    public Person() {
        super();
    }
    
}

4.@Import,ImportSelector和ImportBeanDefinitionRegistrar

@Import导入组件,id默认是组件的全类名

@Import({Color.class,Red.class})

ImportSelector:返回需要导入的组件的全类名数组,需要实现ImportSelector接口

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

    //返回值,就是要导入容器中的组件类全类名
    //AnnotationMetadata:当前标注@Import注解的类的所有注解信息
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        
        //方法不要返回null
        return new String[]{"com.spring.bean.Blue","com.spring.bean.Yellow"};
    }

}

ImportBeanDefinitionRegistrar:手动注册到bean容器中,需要实现ImportBeanDefinitionRegistrar接口

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{

    /**
     * AnnotationMetadata当前类的注解信息
     * BeanDefinitionRegistry:BeanDefinition注册类
     *         把所有需要添加到容器中的bean,调用BeanDefinitionRegistry手动注册进来
     * 
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean red = registry.containsBeanDefinition("com.spring.bean.Red");
        boolean blue = registry.containsBeanDefinition("com.spring.bean.Blue");
        if(red && blue) {
            //指定Bean定义信息,(bean类型)
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
            //注册一个bean,指定bean名
            registry.registerBeanDefinition("rainBow", rootBeanDefinition);
        }
    }

}

不管用哪种方式将组件注册到IOC容器中,组件对应的bean默认都是单实例的,可以通过@Scope("prototype"),将bean调整为多实例的

@Scope调整作用域

singleton 单实例的 默认值    ioc容器启动会调用方法创建对象到ioc容器中,以后每次获取就是直接从容器中拿

prototype 多实例的 ioc容器启动并不会去调用方法创建对象放在容器中,每次获取的时候才会调用方法创建对象

request 同一次请求创建一个实例

session 同一个session创建一个实例

5.@Conditional

@Conditional({Condition})  按照一定的条件进行判断,满足条件给容器注册bean

WindowsCondition类:

public class WindowsCondition implements Condition{

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if(property.contains("Windows")) {
            return true;
        }
        return false;
    }

}

LinuxCondition类:

//判断是否是Linux系统
public class LinuxCondition implements Condition {

    @Override
    /**
     * ConditionContext 判断条件能使用的上下文(环境)
     * AnnotatedTypeMetadata 注释信息
     */
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //是否Linux系统
        //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("Linux")) {
            return true;
        }
        
        return false;
    }

}

将LinuxCondition和WindowsCondition注册进IOC容器中,并添加@Conditional标识

   @Bean("bill")
    @Conditional({WindowsCondition.class})
    public Person person01() {
        return new Person("ber",60);
    }
    
    @Bean("linus")
    @Conditional({LinuxCondition.class})
    public Person person02() {
        return new Person("linux",45);
    }
     ConfigurableEnvironment environment = applicationContext.getEnvironment();
       //动态获取环境变量的值:Windows 10
      String property = environment.getProperty("os.name");
        System.out.println(property);

因为我用的是Windows 10系统,所有,会将person01注册进IOC容器

6.使用Spring提供的FactoryBean(工厂bean),将组件注册进IOC容器

//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {

    //返回一个color对象,这个对象会添加到容器中
    @Override
    public Color getObject() throws Exception {
        // TODO Auto-generated method stub
        System.out.println("ColorFactory.....getObject.....");
        return new Color();
    }

    @Override
    public Class<?> getObjectType() {
        // TODO Auto-generated method stub
        System.out.println("ColorFactory.....getObjectType......");
        return Color.class;
    }

    //是否是单例
    //true,这个bean是单例,在容器中保存一份
    //false,多实例,每次获取都会创建一个新的bean
    @Override
    public boolean isSingleton() {
        // TODO Auto-generated method stub
        return false;
    }

}

将工厂通过@Bean注册进IOC容器

  @Bean
    public ColorFactoryBean colorFactoryBean() {
        return new ColorFactoryBean();
    }
  @Test
    public void testImport() {
        printBeans(applicationContext);
    }
    
    private void printBeans(AnnotationConfigApplicationContext applicationContext) {
        String[] strings = applicationContext.getBeanDefinitionNames();
        for (String string : strings) {
            System.out.println(string);
        }
        
        //工厂bean获取的是调用getObject创建的对象
        Object bean = applicationContext.getBean("colorFactoryBean");
        System.out.println(bean.getClass());
        
        Object bean1 = applicationContext.getBean("&colorFactoryBean");
        System.out.println(bean.getClass());
    }

Spring基于注解配置(四)

原文:https://www.cnblogs.com/TX-wuhe/p/13032287.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!