• 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秒。有时间看下源码有哪些设计。

  • 相关阅读:
    【转】 url中文乱码问题
    [转]Jquery 点击图片在弹出层显示大图
    JQuery获取和设置Select选项的常用方法总结
    springMVC框架下返回json格式的对象,list,map
    sqlserver数据库 表中字段值有空格,如何去除空格(例如char (5) 存入数据不足5位时sqlserver会自动补空格)
    jquery Jbox 插件实现弹出窗口在修改的数据之后,关闭弹出窗口刷新父页面的问题
    sqlserver 2008 r2 直接下载地址,可用迅雷下载
    web服务器与tomcat
    xml入门与解析
    jdbc框架-dbutils的简单使用
  • 原文地址:https://www.cnblogs.com/CreatorKou/p/11328017.html
Copyright © 2020-2023  润新知