zoukankan      html  css  js  c++  java
  • springboot用Depends_ON注解控制bean的依赖关系和创建顺序,用Configuration注解类设置bean之间的关系和多例模式,实现ApplicationContextAware接口后setApplication执行的时机,和访问的自动顺序,阻止空指针异常

    项目+测试+测试配置工程结构:

    本测试类中没有用到src/test/resources的资源文件

    myconfigurations.java
    @Configuration
    public class myconfigurations  {
    
        @Autowired
        private Designgraph dg;
        
        @Bean(name = "car")  
        @Scope("prototype")     
        public Car car() {  
            Car car = new Car();
            car.setDg(dg);
            return car;
        }  
    
    }
    
    Designgraph.java
    //一个设计图纸可以造很多车
    @Component
    public class Designgraph {
        private String graph = "car graph";
        public String Designcar(){
            return "benz"+graph;
        }
    }
    
    Car.java
    public class Car {
        private String name;
        private Designgraph dg;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Designgraph getDg() {
            return dg;
        }
        public void setDg(Designgraph dg) {
            this.dg = dg;
        }    
    }
    
    SpringContextUtil.java
    @Component
    public class SpringContextUtil implements ApplicationContextAware {
        private Logger LOGGER = LoggerFactory.getLogger(SpringContextUtil.class);
     
        // Spring应用上下文环境
        @Autowired
        private static ApplicationContext applicationContext;
     
        /**
         * 实现ApplicationContextAware接口的回调方法,设置上下文环境
         * 
         * @param applicationContext
         */
        @Override
        public void setApplicationContext(ApplicationContext c) {
            
            applicationContext = c;
            LOGGER.info("get appcontext:{}",applicationContext);
        }
     
        
        /**
         * 获取对象 这里重写了bean方法,起主要作用
         * 
         * @param name
         * @return Object 一个以所给名字注册的bean的实例
         * @throws BeansException
         */
        public static Object getBean(String name) throws BeansException {
            return applicationContext.getBean(name);
        } 
    }
    
    testscope.java
    @RunWith(SpringRunner.class)
    @SpringBootTest
    
    public class testscope {
        Logger log = LoggerFactory.getLogger(testscope.class);
    
        @Test
        public void teststaticctx(){
            Car car1 = (Car)SpringContextUtil.getBean("car");
            System.out.println(car1);
            Car car2 = (Car)SpringContextUtil.getBean("car");
            System.out.println(car2);
        }
     
    }

    如果在myconfigurations.java的car()方法上没有添加  @Scope("prototype")这个注解,那么在testscope.java中调用SpringContextUtil.getBean("car")每次得到的都是同一个Bean

    所以为了保证car多例, @Scope("prototype")这个注解是必须的;

    怎样可以将SpringContextUtil.java的捕获ApplicationContext的功能结合到myconfigurations.java中?

    怎样控制bean创建顺序,逻辑顺序?时间顺序?

    代码地址:

    https://github.com/KouReal/springbootstudy_buycar

    myconfigurations实现了ApplicationContextAware接口,按照接口要求定义了setApplicationContext(Applicationcontext appcontext)方法;

    然后自己为myconfigurations添加了static applicationcontext字段,static getBean(String name)方法;

    现在要测试,在springboot启动后,主线程,其他线程都访问myconfigurations的applicationcontext字段,然后访问getbean方法,看看是否会有空指针异常,就是考虑是否会在myconfigurations完成实例化之前就执行到测试线程和其他线程的getbean方法,从而导致nullpointerexeception。

    故意在myconfigurations的setApplicationContext(Applicationcontext appcontext)方法中设置了8秒的sleep

    @Configuration
    public class myconfigurations implements ApplicationContextAware{
        Logger log = LoggerFactory.getLogger(myconfigurations.class);
        public static ApplicationContext applicationcontext;
        ...
        
        @Bean(name="test222")
        public Test222 test222(){
            return new Test222();
        }
    
        @Override
        public void setApplicationContext(ApplicationContext actx) throws BeansException {
            try {
                log.info("setapplicationcontext sleep 8000:thread:{}",Thread.currentThread());
                Thread.currentThread().sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            // TODO Auto-generated method stub
            applicationcontext=actx;
        }  
        public static Object getBean(String name) throws BeansException {
            return applicationcontext.getBean(name);
        }
    
    }
    class Test222{
        private int i;
    }
    @Test
        public void teststaticctx(){
            //test context
            ApplicationContext act = myconfigurations.applicationcontext;
            System.out.println("act is : "+act);
            try{
                Test222 test222 = (Test222) myconfigurations.getBean("test222");
                System.out.println("test222:"+test222);
            }catch(Exception e){
                System.out.println("getBean遭遇异常:"+e.getLocalizedMessage());
            }
            Thread th = new Thread(new Runnable() {
                
                @Override
                public void run() {
                    //test context
                    ApplicationContext act = myconfigurations.applicationcontext;
                    System.out.println("act is : "+act);
                    try{
                        Test222 test222 = (Test222) myconfigurations.getBean("test222");
                        System.out.println("test222:"+test222);
                    }catch(Exception e){
                        System.out.println("getBean遭遇异常:"+e.getLocalizedMessage());
                    }
                    
                    //boss买车
                    log.info("testscope:thread:{}",Thread.currentThread());
                    System.out.println(boss.seegrapth());
                    Car car1 = (Car)myconfigurations.getBean("car");
                    Car car2 = (Car)myconfigurations.getBean("car");
                    System.out.println("boss buy:"+car1.getcontent());
                    System.out.println("boss buy:"+car2.getcontent());
                    try {
                        log.info("boss sleep...:thread:{}",Thread.currentThread());
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println("boss wake up");
                    Car car3 = (Car)myconfigurations.getBean("car");
                    System.out.println("boss buy:"+car3.getcontent());
                }
            });
            th.start();
            
            try {
                th.join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }

    myconfigurations实现了ApplicationContextAware接口,按照接口要求定义了setApplicationContext(Applicationcontext appcontext)方法;

    然后自己为myconfigurations添加了static applicationcontext字段,static getBean(String name)方法;

    现在要测试,在springboot启动后,主线程,其他线程都访问myconfigurations的applicationcontext字段,然后访问getbean方法,看看是否会有空指针异常,就是考虑是否会在myconfigurations完成实例化之前就执行到测试线程和其他线程的getbean方法,从而导致nullpointerexeception。

    故意在myconfigurations的setApplicationContext(Applicationcontext appcontext)方法中设置了8秒的sleep

    经过测试,发现没有发生上述现象,无论主线程还是其他线程都在阻塞等待8秒。有时间看下源码有哪些设计。

  • 相关阅读:
    VMWARE Linux环境下如何设置共享文件夹?
    linux本地源#如何挂载本地iso镜像作为本地源
    centos7修改系统语言为简体中文
    Redhat镜像-RHEL-官方镜像下载大全
    如何连接到Oracle数据库?
    Oracle 数据库创建导入
    Oracle 12C安装教程
    Oracle 11g安装
    Linux下安装Oracle11g服务器
    Oracle简介
  • 原文地址:https://www.cnblogs.com/CreatorKou/p/11328017.html
Copyright © 2011-2022 走看看