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