zoukankan      html  css  js  c++  java
  • 多个@Configuration配置文件,引用方式。多配置文件引用时提示could not autowired时,没有扫描到注解所在的包。springboot中,ContextLoader.getCurrentWebApplicationContext()获取的为Null

    当需要一个 Bean 初始化后,利用其实例方法或者其他巴拉巴拉,来初始化当前 Bean ,引用方式。

    引用方式

    1、注入时添加 不必要 条件

    2、添加 @DependsOn 或 @ConditionalOnBean注解,参数调用

    3.  依赖不太复杂时,可使用 @Lazy 注解 

    配置类1

    package cc.ash.config;
    
    import cc.ash.bo.Course;
    import cc.ash.bo.Student;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.*;
    
    @Slf4j
    @Configuration
    public class InitConfig {
    
        /**
         * 1、注入时添加 不必要 条件
         * 2、添加 DependsOn 注解,参数调用其对象方法
         * 3. 依赖不太复杂时,可使用 @Lazy 注解
         */
        @Autowired(required = false)
        Course course;
    
        /**
         * @Dependson注解是在另外一个实例创建之后才创建当前实例,也就是,最终两个实例都会创建,只是顺序不一样
         *
         * @ConditionalOnBean注解是只有当另外一个实例存在时,才创建,否则不创建,也就是,最终有可能两个实例都创建了,有可能只创建了一个实例,也有可能一个实例都没创建
         */
        @Bean
        @Scope("prototype") //singleton(默认)、prototype、request、session
        @DependsOn(value = {"course"})
        public Student stu(Course course) {
            log.info(">>>>>>>>>>>>>>>>>>" + course.toString());
            return new Student();
        }
    }

    配置类2

    package cc.ash.config;
    
    import cc.ash.bo.Course;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class InitialConfig {
    
        @Bean
        public Course course() {
            return new Course();
        }
    }

    启动类

    (不在基础包下,添加基础包扫描注解)

    package cc.ash.springcloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.ComponentScan;
    
    @ComponentScan(value = "cc.ash")
    @SpringBootApplication
    public class PaymentMain8001 {
    
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain8001.class, args);
        }
    }

    junit测试类

    package cc.ash.test;
    
    import cc.ash.config.ApplicationContextRegister;
    import cc.ash.springcloud.PaymentMain8001;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.context.ApplicationContext;
    import org.springframework.test.context.junit4.SpringRunner;
    import org.springframework.web.context.ContextLoader;
    import org.springframework.web.context.WebApplicationContext;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = PaymentMain8001.class)
    public class Test {
    
        @org.junit.Test
        public void test() {
    
            System.out.println("Test.test");
    
            ApplicationContext applicationContext = ApplicationContextRegister.getApplicationContext();
            Object course1 = applicationContext.getBean("course");
    
            WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
            // java.lang.NullPointerException
            Object course = context.getBean("course");
        }
    
    }

    获取上下文配置类

    >>> springboot中,ContextLoader.getCurrentWebApplicationContext()获取的为Null

    springboot无论以main方法还是spring-boot:run的方式执行都不会跑SpringBootServletInitializer中的onStartup导致ContextLoaderListener没有执行。考虑到以往的经验ContextLoaderListener一般是配置在web.xml中的对web容器有依赖,所以我直接把工程打成war放到tomcat跑果然可以调用SpringBootServletInitializer中的onStartup,但是还是不能获取ContextLoader.getCurrentWebApplicationContext(),原因是在onStartup初始化ContextLoader时使用的是构造函数,没有用ContextLoader.initWebApplicationContext方式,所以获取不到,要用这种方式得重写SpringBootServletInitializer中的onStartup

    package cc.ash.config;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.stereotype.Component;
    
    /**
     * 确实有这个问题,我debug了一下源码,发现springboot无论以main方法还是spring-boot:run的方式执行都不会跑
     * SpringBootServletInitializer中的onStartup导致ContextLoaderListener没有执行。
     * 考虑到以往的经验ContextLoaderListener一般是配置在web.xml中的对web容器有依赖,
     * 所以我直接把工程打成war放到tomcat跑果然可以调用SpringBootServletInitializer中的onStartup,
     * 但是还是不能获取ContextLoader.getCurrentWebApplicationContext(),
     * 原因是在onStartup初始化ContextLoader时使用的是构造函数,
     * 没有用ContextLoader.initWebApplicationContext方式,所以获取不到,
     * 要用这种方式得重写SpringBootServletInitializer中的onStartup
     *
     * ApplicationContextRegister.getApplicationContext() .getBean("xx");就可以获取对应的bean
     */
    @Component
    @Lazy(false)
    public class ApplicationContextRegister implements ApplicationContextAware {
        private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationContextRegister.class);
        private static ApplicationContext APPLICATION_CONTEXT;
    
        /**
         * 设置spring上下文 
         */
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            LOGGER.debug("ApplicationContext registed-->{}", applicationContext);
            APPLICATION_CONTEXT = applicationContext;
        }
    
        public static ApplicationContext getApplicationContext() {
            return APPLICATION_CONTEXT;
        }
    }

    .

  • 相关阅读:
    [转]MyBatis传入多个参数的问题
    【转】赶集网mysql开发36军规
    C#套接字和windowsAPI套接字
    java中的注解
    java中的枚举类型
    过去的汇编代码
    近日错误集锦
    java swing模仿随机频谱
    java泛型中的对象
    XML-RPC远程方法调用
  • 原文地址:https://www.cnblogs.com/foolash/p/13795159.html
Copyright © 2011-2022 走看看