當需要一個 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; } }
.