zoukankan      html  css  js  c++  java
  • Spring高级注解

    目录:

    1、使用限定注解;
    2、自定义限定注解;
    3、自定义bean的生命周期;

    开发环境:IntelliJ IDEA 2019.2.2
    Spring Boot版本:2.1.8
    新建一个名称为demo的Spring Boot项目。

    一、限定注解

    当存在多个同类型的bean时,可以使用Primary注解指定优先注入的bean。如果对bean的注入选择做进一步的控制,则可以使用限定注解。
    限定注解可以与特定的参数关联起来,缩小类型匹配的范围,最后选择一个符合条件的bean来注入。

    1、新建类 MyBean.java

    package com.example.demo;
    
    public class MyBean {
    
        public MyBean(String id){
           this.id = id;
        }
    
        private String id;
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    }

    2、新建类 MyConfig.java

    package com.example.demo;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class MyConfig {
    
        @Bean
        public MyBean bean1(){
            return new MyBean("1");
        }
    
        @Bean
        public MyBean bean2(){
            return new MyBean("2");
        }
    }

    3、新建一个控制器 DemoController.java

    package com.example.demo;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class DemoController {
    
        @Autowired
        @Qualifier("bean1")
        MyBean bean;
    
        @RequestMapping(value = "/")
        public String index(){
            return bean.getId();
        }
    }

    运行项目后,浏览器访问:http://localhost:8080/,页面显示:
    1

    二、自定义限定注解

    如果需要根据特定的属性来指定注入的bean,则可以自定义限定注解。

    1、继续使用上面例子的类 MyBean.java

    2、新建一个接口 MyBeanQualifier.java

    package com.example.demo;
    
    import org.springframework.beans.factory.annotation.Qualifier;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({ElementType.FIELD, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Qualifier
    public @interface MyBeanQualifier {
        String type();
    }

    3、修改上面例子代码 MyConfig.java
    在配置bean时,需要为相应的bean设置不同的类型。

    package com.example.demo;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class MyConfig {
    
        @Bean
        @MyBeanQualifier(type = "bean1")
        public MyBean bean1(){
            return new MyBean("1");
        }
    
        @Bean
        @MyBeanQualifier(type = "bean2")
        public MyBean bean2(){
            return new MyBean("2");
        }
    }

    4、修改上面例子控制器代码 DemoController.java

    package com.example.demo;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class DemoController {
    
        @Autowired
        @MyBeanQualifier(type = "bean2")
        MyBean bean;
    
        @RequestMapping(value = "/")
        public String index(){
            return bean.getId();
        }
    }

    运行项目后,浏览器访问:http://localhost:8080/,页面显示:
    2

    三、自定义bean的生命周期

    Scope注解主要用于配置bean在容器中的生命周期,除了可以配置为singleton和prototype,在Web环境还可以配置为request、session等
    值,表示容器会为一次请求或一个会话分配一个bean的实例。
    如果对bean的生命周期有特殊需求,可以使用自定义的Scope。
    例子:一个bean被使用3次后,就获取新的bean实例。

    1、继续使用上面例子的类 MyBean.java

    2、新建一个自定义的Scope类 MyScope.java

    package com.example.demo;
    
    
    import org.springframework.beans.factory.ObjectFactory;
    import org.springframework.beans.factory.config.Scope;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class MyScope implements Scope {
        //记录bean的使用次数
        private Map<String,Integer> beanCounts = new HashMap<String,Integer>();
        //保存实例
        private Map<String,Object> beans = new HashMap<String,Object>();
    
        @Override
        public Object get(String s, ObjectFactory<?> objectFactory) {
            if(beanCounts.get(s) == null){
                beanCounts.put(s, 0);
            }
            //第一次使用,放到实例的Map中
            Integer beanCount = beanCounts.get(s);
            if(beanCount == 0){
                Object newObject = objectFactory.getObject();
                beans.put(s, newObject);
            }
            Object bean = beans.get(s);
            //计数器加1
            Integer newBeanCount = beanCount + 1;
            if(newBeanCount >= 3){
                newBeanCount = 0;
            }
            //设置新的次数
            beanCounts.put(s, newBeanCount);
            return bean;
        }
    
        @Override
        public Object remove(String s) {
            return null;
        }
    
        @Override
        public void registerDestructionCallback(String s, Runnable runnable) {
    
        }
    
        @Override
        public Object resolveContextualObject(String s) {
            return null;
        }
    
        @Override
        public String getConversationId() {
            return null;
        }
    }

    3、修改上面例子代码 MyConfig.java
    将自定义Scope注册到容器中。

    package com.example.demo;
    
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.beans.factory.config.CustomScopeConfigurer;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Scope;
    
    import javax.annotation.PostConstruct;
    
    @Configuration
    public class MyConfig {
    
        @Autowired
        BeanFactory factory;
    
        @PostConstruct
        public void customScopeConfigurer(){
            CustomScopeConfigurer config = new CustomScopeConfigurer();
            config.addScope("three", new MyScope());
            config.postProcessBeanFactory((ConfigurableListableBeanFactory)factory);
        }
    
        @Bean
        @Scope(scopeName = "three")
        public MyBean bean1(){
            return new MyBean("1");
        }
    
    }

    4、修改上面例子控制器代码 DemoController.java

    package com.example.demo;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class DemoController {
    
        @Autowired
        ApplicationContext ctx;
    
        @RequestMapping(value = "/")
        public String index(){
            for(int i=0;i<5;i++){
                System.out.println(ctx.getBean("bean1"));
            }
            return "";
        }
    }

    运行项目后,浏览器访问:http://localhost:8080/,IDEA控制台输出:
    com.example.demo.MyBean@61f13a02
    com.example.demo.MyBean@61f13a02
    com.example.demo.MyBean@61f13a02
    com.example.demo.MyBean@54094334
    com.example.demo.MyBean@54094334

    可见前3次得到同一个bean实例。

    附,项目结构图

  • 相关阅读:
    U盘安装WIN10专业版
    jquery template模版引擎
    MySQL大数据量快速分页实现(转载)
    MySQL for Windows 解压缩版安装 和 多实例安装
    macbook 重装win7
    MySQL for Visual Studio Version
    VS2010中没有ado.net entity data model实体数据模型这一选项-解决办法
    修改server 2008远程桌面端口
    懒加载
    html-css 常用
  • 原文地址:https://www.cnblogs.com/gdjlc/p/11610484.html
Copyright © 2011-2022 走看看