@PostConstruct - 静态方法调用IOC容器Bean对象
需求:工具类里引用IOC容器中的Bean,强迫症患者在调用工具类时喜欢用静态方法的方式而非注入的方式去调用,但是spring 不支持注解注入静态成员变量。
- 静态变量/类变量不是对象的属性,而是一个类的属性,spring是基于对象层面的依赖注入。静态变量不属于对象,只属于类,也就是说在类被加载字节码的时候变量已经初始化了,也就是给该变量分配内存了,导致spring忽略静态变量。
举个栗子:
@Component public class MessageUtil { @Resource private static MerchantService merchantService; public static void getMerchant1(Long id) { System.out.println(merchantService.getMerchantByMchId(id)); } }
调用
注入方式调用工具类 @Resource private MessageUtil messageUtil; public void ttt1() { messageUtil.getMerchant1(2L); } 静态方法调用工具类 public void ttt() { MessageUtil.getMerchant(2L); }
可以将对象托管给spring管理。
- 执行过程如下:①在IOC容器初始化的时候创建实例对象 ②执行完构造函数 ③执行注解@Resource ④执行PostConstruct注解。
- 这里解释为什么不能在构造函数中但可以用PostConstruct借用注解注入的对象赋值静态属性。因为构造函数执行的时候,注解中的对象还未执行,为null;而PostConstruct是在注解注入对象之后执行
利用@PostConstruct注解可以解决该问题
代码如下 - 2种写法。原理一致。
@Component public class MessageUtil { @Resource private MerchantService merchantService; private static MerchantService merchantServiceStatic; /** * 需求是 : 要在静态方法里面调用IOC容器的bean对象 * PostConstruct 在构造函数执行之后执行。 * 可以方便的把注入的bean对象给到静态属性 */ @PostConstruct public void postConstruct() { merchantServiceStatic = this.merchantService; } public static void getMerchant(Long id) { System.out.println(merchantServiceStatic.getMerchantByMchId(id)); } }
@Component public class MessageUtil { @Resource private MerchantService merchantService; private static MessageUtil messageUtil; /** * 需求是 : 要在静态方法里面调用IOC容器的bean对象 * PostConstruct 在构造函数执行之后执行。 * 可以方便的把注入的bean对象给到静态属性 */ @PostConstruct public void postConstruct() { messageUtil = this; } public static void getMerchant(Long id) { System.out.println(messageUtil.merchantService.getMerchantByMchId(id)); } }
如果工具类需要注入的对象较多,推荐第二种。这样代码比较少。
如果需要注入的对象只有一个,推荐第一种,语义比较清晰
@PostConstruct注解原理参考 https://www.jianshu.com/p/98cf7d8b9ec3
是谁来自江河湖海,却囿于昼夜厨房与爱