• Spring组件注册


    Spring组件注册

    @Bean

    代码演示@Bean注解的使用

    Dept

    @NoArgsConstructor
    @AllArgsConstructor
    @Data
    @ToString
    @Component
    public class Dept {
        private String id;
        private String name;
    }

    SpringConfig

    @Configuration
    public class SpringConfig {
    
        @Bean()
        public Dept dept(){
        return new Dept("001","财务部"); } }

    通过@Bean注解,我们向IOC容器中注册了一个名称为dept的对象,Bean的默认名称为方法的 名称。 下面在启动类中测试从IOC容器中获取这个对象。

    SpringDemoApplication

    @SpringBootApplication
    public class SpringDemoApplication {
    
        public static void main(String[] args) {
            //SpringApplication.run(SpringDemoApplication.class, args);
    
            // 返回 IOC 容器,使用注解配置,传入配置类
            ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
            Dept dept = context.getBean(Dept.class);
            System.out.println(dept);
        }
    }

    控制台打印

    Dept(id=001, name=财务部)

    我们可以自己指定组件的名称

    @Bean(value = "myDept")
    public Dept dept(){
    return new Dept("001","财务部");
    }

    启动类

    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    String[] beanNames = context.getBeanNamesForType(Dept.class);
    Arrays.stream(beanNames).forEach(System.out::println);

    控制台打印

    myDept

    @ComponentScan

    使用@ComponentScan注解进行扫描。

    修改配置类

    @Configuration
    @ComponentScan(value = "cn.xupengzhuang.springdemo")
    public class SpringConfig {
    }

    在Controller、Service、Dao、pojo等包下的类上分别加上@Controller、@Service、 @Repository、@Component等注解

    代码层次结构

    启动类

    // 返回 IOC 容器,使用注解配置,传入配置类
    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    String[] beanDefinitionNames = context.getBeanDefinitionNames();
    Arrays.stream(beanDefinitionNames).forEach(System.out::println);

    控制台打印

    springConfig
    deptController
    deptDao
    dept
    deptService

    组件已经全部被扫描进去了,默认名称是类名字的首字母小写。

    指定扫描策略1

    @Configuration
    @ComponentScan(value = "cn.xupengzhuang.springdemo",
        excludeFilters = {
            @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class),
            @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = Dept.class)
        })
    public class SpringConfig {
    
    
    }

    除了@Controller注解标注的类以及Dept这个实体类,剩余的对象都将被扫描到IOC容器中。

    控制台打印

    springConfig
    deptDao
    deptService

    指定扫描策略2

    @Configuration
    @ComponentScan(value = "cn.xupengzhuang.springdemo",
        includeFilters = {
            @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class),
            @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = Dept.class)
        },useDefaultFilters = false)
    public class SpringConfig {
    
    
    }

    会将@Controller注解标注的类、Dept类进行扫描。

    控制台打印

    springConfig
    deptController
    dept

    指定扫描策略3-自定义

    自定义扫描策略需要我们实现org.springframework.core.type.filter.TypeFilter接口

    创建MyTypeFilter实现该接口

    public class MyTypeFilter 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();
            // 获取当前正在扫描的类的路径等信息
            Resource resource = metadataReader.getResource();
    
            String className = classMetadata.getClassName();
    
    
            return className.contains("dept");
        }
    }

    SpringConfig

    @Configuration
    @ComponentScan(value = "cn.xupengzhuang.springdemo",
        excludeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM,classes = MyTypeFilter.class)},
            useDefaultFilters = false)
    public class SpringConfig {
    
    
    }
    控制台打印
    springConfig

    @Scope

    默认情况下,在Spring的IOC容器中每个组件都是单例的,即无论在任何地方注入多少次, 这些对象都是同一个。

    配置类

    @Configuration
    public class SpringConfig {

    @Bean(value = "myDept")
    public Dept dept(){
    return new Dept("001","财务部");
    }

    }

    启动类

    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    Object myDept1 = context.getBean("myDept");
    Object myDept2 = context.getBean("myDept");
    System.out.println(myDept1 == myDept2);

    控制台打印

    true

    在Spring中我们可以使用@Scope注解来改变组件的作用域:

    • singleton:单实例(默认),在Spring IOC容器启动的时候会调用方法创建对象 然后纳入到IOC容器中,以后每次获取都是直接从IOC容器中获取。
    • prototype:多实例,IOC容器启动的时候并不会去创建对象,而是在每次获取的 时候才会去调用方法创建对象。
    • request:一个请求对应一个实例。
    • session:同一个session对应一个实例。

    @Lazy

    懒加载是针对单例模式而言的,正如前面所说,IOC容器中的组件默认是单例的,容器启动 的时候会调用方法创建对象然后纳入到IOC容器中。

    在DeptBean注册的地方加一行打印

    @Configuration
    public class SpringConfig {
    
        @Bean(value = "myDept")
        public Dept dept(){
            System.out.println("往IOC中注册Dept");
            return new Dept("001","财务部");
        }
    
    }

    启动类

    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    System.out.println("容器创建完毕");

    控制台打印

    往IOC中注册Dept
    容器创建完毕

    Dept修改为懒加载方式

    @Configuration
    public class SpringConfig {
    
        @Bean(value = "myDept")
        @Lazy
        public Dept dept(){
            System.out.println("往IOC中注册Dept");
            return new Dept("001","财务部");
        }
    
    }

    控制台打印

    容器创建完毕

    可以验证,在容器创建完成的时候,这个组件并没有加到容器中。 所以在单例模式中,IOC容器创建的时候,对于懒加载的组件,并不会马上去调用方法创建 对象并注册,只有第一次使用的时候才会调用方法创建对象并加入到容器中。

    修改启动类进行验证

    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    System.out.println("容器创建完毕");
    Object myDept2 = context.getBean("myDept");

    控制台打印

    容器创建完毕
    往IOC中注册Dept

     可以发现在context.getBean("myDept");代码执行之后,才会往IOC容器中注册myDept组件。

     

  • 相关阅读:
    【阿里天池云-龙珠计划】薄书的机器学习笔记——快来一起挖掘幸福感!Task04
    薄书的pytorch项目实战lesson49-情感分类+蹭免费GPU
    薄书的博客园主题——awescnb
    # 详细分析MySQL事务日志(redo log和undo log)
    docker网络模式
    IOTOP
    磁盘分区知识
    # KVM虚拟化技术的内置快照和外置快照
    mysql MGR
    linux各种监控工具 (转)
  • 原文地址:https://www.cnblogs.com/beanbag/p/13374761.html
Copyright © 2020-2023  润新知