多個@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;
    }
}

 

.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM