spring容器载入bean顺序是不肯定的,spring框架没有约定特定顺序逻辑规范。但spring保证若是A依赖B(如beanA中有@Autowired B的变量),那么B将先于A被加载。但若是beanA不直接依赖B,咱们如何让B仍先加载呢?spring
须要的场景距离以下数组
间接(并非直接@Autowired)
依赖 bean B。如bean A有一个属性,须要在初始化的时候对其进行赋值(须要在初始化的时候作,是由于这个属性实际上是包装了其它的几个Bean的,好比说代理了Bean B),因此这就造成了Bean A间接的依赖Bean B了以上是两种典型的,Bean初始化的时候存在依赖关系的状况,均可以经过@DependsOn
来解决 。app
例子框架
准备工做:(两个controller和一个service)函数
@Controller public class HelloController { public HelloController() { System.out.println("HelloController 初始化。。。"); } @ResponseBody @GetMapping("/hello") public String helloGet() throws Exception { return "hello...Get"; } } @Controller public class AsyncHelloController { public AsyncHelloController() { System.out.println("AsyncHelloController 初始化。。。"); } } @Service public class HelloServiceImpl implements HelloService { public HelloServiceImpl() { System.out.println("HelloServiceImpl 初始化。。。"); } }
启动容器,打印顺序(初始化顺序以下:)spa
HelloServiceImpl 初始化。。。 AsyncHelloController 初始化。。。 HelloController 初始化。。。
须要注意的是:这个demo的日志都是放在默认的构造函数里面的,所以即便你使用了@Autowired
,也是不会打乱构造函数的执行顺序的,由于,由于@Autowired的解析发生在给属性赋值的populate()方法里,这个时候本身已经实例化了,才会去给属性赋值, 因此若是你要求的时机稍微比较晚能够在赋值期间、或者实例化期间。代理
//@DependsOn // 这里面写String数组。不写不会生效,可是若写了,名字要写正确,不然会报错的 @DependsOn({"helloController"}) // 名称必须写对,必须是容器里存在的Bean,不然启动报错的(fast-fail是好事) @Controller public class AsyncHelloController { ... } HelloServiceImpl 初始化。。。 HelloController 初始化。。。 --> HelloController先被实例化了~~~ AsyncHelloController 初始化。。。
使用@Lazy间接实现日志
@Lazy public class AsyncHelloController { ... } HelloServiceImpl 初始化。。。 HelloController 初始化。。。
咱们发现它只有两句输出,这个时候AsyncHelloController
尚未实例化。只有首次访问它的时候才会实例化,因此咱们是经过间接的方式
实现了这个效果。code