ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring注解驱动——组件注册系列

2019-12-18 23:00:47  阅读:117  来源: 互联网

标签:容器 return Spring public Person Bean 组件 注解 class


1.@Configuration

  从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

  用法:

@Configuration
public class TestConfiguration {
    public TestConfiguration() {
        System.out.println("TestConfiguration容器启动初始化。。。");
    }
}

 

2.@Bean

  给IOC容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id。 相当于<bean></bean>

  用法:

    Bean类:

package com.springs.entity;


import org.springframework.beans.factory.annotation.Value;

public class Person {

    private String name;
    private Integer age;
    private String nickName;
     
    
    public String getNickName() {
        return nickName;
    }
    public void setNickName(String nickName) {
        this.nickName = nickName;
    }
    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;
    }
    
    public Person(String name, Integer age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Person() {
        super();
        // TODO Auto-generated constructor stub
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", nickName=" + nickName + "]";
    }

    Bean注入:

@Configuration//告诉Spring这是一个配置类

public class MainConfig {

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

  

3.@ComponentScan

  在配置类上添加 @ComponentScan 注解。该注解默认会扫描该类所在的包下所有的配置类,相当于之前的 <context:component-scan>。

  3.1 基本使用

@Configuration//告诉Spring这是一个配置类
@ComponentScan(value = "com.springs")

public class MainConfig {

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

  3.2 excludeFilters 和 includeFilters 的使用

  •   excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
  •   includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件

      excludeFilters 和 includeFilters 的参数是一个 Filter[] 数组,然而每一个Filter也是一个注解,打开filter来看,我们知道需要设置一个过滤类型和使用的类

    

//FilterType.ANNOTATION:按照注解
//FilterType.ASSIGNABLE_TYPE:按照给定的类型;
//FilterType.ASPECTJ:使用ASPECTJ表达式
//FilterType.REGEX:使用正则指定
//FilterType.CUSTOM:使用自定义规则

    3.2.1 使用(一):注解过滤的使用

@Configuration//告诉Spring这是一个配置类
@ComponentScan(value = "com.springs",includeFilters = {
        @ComponentScan.Filter(type= FilterType.ANNOTATION,classes={Controller.class})},useDefaultFilters = false)

//excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
//includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
//FilterType.ANNOTATION:按照注解
//FilterType.ASSIGNABLE_TYPE:按照给定的类型;
//FilterType.ASPECTJ:使用ASPECTJ表达式
//FilterType.REGEX:使用正则指定
//FilterType.CUSTOM:使用自定义规则
public class MainConfig {

    }
}

    这里涉及到 @ComponentScan 的一个 useDefaultFilters 属性的用法,该属性默认值为 true,也就是说 spring 默认会自动发现被 @Component 、@Repository、@Service 和 @Controller 标注的类,并注册进容器中。要达到只包含某些包的扫描效果,就必须将这个默认行为给禁用掉(在 @ComponentScan 中将 useDefaultFilters 设为 false 即可)

    3.2.2 使用(二):自定义过滤规则

      实现TypeFilter类:

public class MyTypeFilter implements TypeFilter {
    /**
     * metadataReader:读取到的当前正在扫描的类的信息
     * metadataReaderFactory:可以获取到其他任何类信息的
     */
    @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("er")){
            return true;
        }
        return false;
    }

}

      使用自动规则:

@Configuration//告诉Spring这是一个配置类
@ComponentScan(value = "com.springs",includeFilters = {
        @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
},useDefaultFilters = false)

public class MainConfig {


}

  3.3 添加多种扫描规则

     如果使用的 jdk8,则可以直接添加多个 @ComponentScan 来添加多个扫描规则

    可以使用 @ComponentScans 来添加多个 @ComponentScan,从而实现添加多个扫描规则

@Configuration//告诉Spring这是一个配置类
@ComponentScan(value = "com.springs",includeFilters = {
        @ComponentScan.Filter(type= FilterType.ANNOTATION,classes={Controller.class}),
        @ComponentScan.Filter(type =FilterType.ASSIGNABLE_TYPE,classes = {MainService.class}),
        @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
},useDefaultFilters = false)


//@ComponentScan  value:指定要扫描的包
//@ComponentScans({@ComponentScan(),@ComponentScan()})  定义多个扫描规则
//excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
//includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
//FilterType.ANNOTATION:按照注解
//FilterType.ASSIGNABLE_TYPE:按照给定的类型;
//FilterType.ASPECTJ:使用ASPECTJ表达式
//FilterType.REGEX:使用正则指定
//FilterType.CUSTOM:使用自定义规则
public class MainConfig {

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

 

4.@Scope

  用来调整作用域,默认是单例模式,即scope="singleton"。另外scope还有prototype、request、session、global session作用域。

  •   prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象;
  •   singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。以后每次获取就是直接从容器(map.get())中拿,
  •   request:同一次请求创建一个实例
  •   session:同一个session创建一个实例
    @Scope("prototype")
    @Bean("person")
    public Person person(){
        System.out.println("给容器中添加Person....");
        return new Person("张三", 25);
    }

 

5.@lazy

   单实例bean:默认在容器启动的时候创建对象。而懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化;

 @Lazy
    @Bean("person")
    public Person person(){
        System.out.println("给容器中添加Person....");
        return new Person("张三", 25);
    }

 

6.@Conditional

  @Conditional是Spring4新提供的注解,它的作用是根据某个条件创建特定的Bean,通过实现Condition接口,并重写matches接口来构造判断条件。

  既可以用在类上(满足当前条件,这个类中配置的所有bean注册才能生效;),也可以用在方法上

  用法:

    linux系统条件

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

        //可以判断容器中的bean注册情况,也可以给容器中注册bean
        boolean definition = registry.containsBeanDefinition("person");
        if(property.contains("linux")){
            return true;
        }

        return false;
    }

    Windows系统条件:

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;
    }

}

    配置类:

 /**
     * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean
     *
     * 如果系统是windows,给容器中注册("bill")
     * 如果是linux系统,给容器中注册("linus")
     */
    @Conditional({WindowsCondition.class})
    @Bean("bill")
    public Person person01(){
        return new Person("Bill Gates",62);
    }

    @Conditional(LinuxCondition.class)
    @Bean("linus")
    public Person person02(){
        return new Person("linus", 48);
    }

  

7.@import

  有时没有把某个类注入到IOC容器中,但在运用的时候需要获取该类对应的bean,此时就需要用到@Import注解。id默认是组件的全类名

  7.1 基本用法:

    创建一个类:

package com.springs.entity;
public class Color {

}

    使用import导入

@Import({Color.class})
//@Import导入组件,id默认是组件的全类名
public class TwoConfig {
}

  7.2 ImportSelector

    返回需要导入的组件的全类名数组;

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

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

}

  7.3 ImportBeanDefinitionRegistrar

    手动注册bean到容器中,可以指定其注入名称

ublic class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * AnnotationMetadata:当前类的注解信息
     * BeanDefinitionRegistry:BeanDefinition注册类;
     *         把所有需要添加到容器中的bean;调用
     *         BeanDefinitionRegistry.registerBeanDefinition手工注册进来
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        boolean definition = registry.containsBeanDefinition("com.springs.entity.Red");
        boolean definition2 = registry.containsBeanDefinition("com.springs.entity.Blue");
        if(definition && definition2){
            //指定Bean定义信息;(Bean的类型,Bean。。。)
            RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
            //注册一个Bean,指定bean名
            registry.registerBeanDefinition("rainBow", beanDefinition);
        }
    }

}

 

8.使用Spring提供的 FactoryBean(工厂Bean)注册组件

  •   默认获取到的是工厂bean调用getObject创建的对象
  •   要获取工厂Bean本身,我们需要给id前面加一个& :&colorFactoryBean
//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {

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

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

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

}
    @Bean
    public ColorFactoryBean colorFactoryBean(){
        return new ColorFactoryBean();
    }

 

10.总结:

 /**
     * 给容器中注册组件;
     * 1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类]
     * 2)、@Bean[导入的第三方包里面的组件]
     * 3)、@Import[快速给容器中导入一个组件]
     *         1)、@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
     *         2)、ImportSelector:返回需要导入的组件的全类名数组;
     *         3)、ImportBeanDefinitionRegistrar:手动注册bean到容器中
     * 4)、使用Spring提供的 FactoryBean(工厂Bean);
     *         1)、默认获取到的是工厂bean调用getObject创建的对象
     *         2)、要获取工厂Bean本身,我们需要给id前面加一个&
     *             &colorFactoryBean
     */

标签:容器,return,Spring,public,Person,Bean,组件,注解,class
来源: https://www.cnblogs.com/xiao-ran/p/12064467.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有