Invoke Spring-managed Beans in static methods (tool classes)

Scenes:

  • Package tools to facilitate business processing
  • Beans managed by spring need to be called in the tool class
  • The test call reports a null pointer exception problem

Preliminary tool code:

@Component
public class ScriptExecuteContent {

@Autowired
private static SignRepository signRepository;

public static String checkSign(String certNo, String acctNo, String instCode) {
    Sign sign = signRepository.findByCertNoAndAcctNoAndInstCode(certNo, acctNo, instCode);
    if (null != sign
            && StringUtils.equals(sign.getStatus(), StatusEnum.SUCCESS.code())
            && DateUtil.getCurrentDate().before(sign.getExpireTime())) {
        return "1";
    } else {
        return "0";
    }
}
}

This piece of code is dazzling and there is nothing wrong with it, but it will run with a null exception, because the signRepository injected here is null. This is because the static method belongs to the class, and the ordinary method belongs to the object. Spring injection is instantiated in the container. Variables, and static exists in preference to objects, so the static variables injected directly in the static method are actually null.

Thinking: 

 

The life cycle of Spring Bean:

Instantiation and property assignment correspond to the injection of constructor and setter methods, initialization and destruction are two stages that users can customize and extend

  • Instantiation
  • Attribute assignment Populate
  • Initialization
  • Destruction

Initialization ==> 4 methods of Bean object transformation:

When to call the Destruction phase:

  • Single instance: when the container is closed
  • Multi-instance: The container will not manage this Bean, and will not call its destruction method
     

 

Solution one:

 @Autowired is used in the constructor

We know that the @Autowired annotation can annotate class member variables, methods and constructors to complete the work of automatic assembly. This way is to use @Autowired on the constructor.

@Component
public class ScriptExecuteContent {

private static SignRepository signRepository;

@Autowired
public ScriptExecuteContent(SignRepository signRepository) {
    ScriptExecuteContent.signRepository = signRepository;
}

public static String checkSign(String certNo, String acctNo, String instCode) {
    Sign sign = signRepository.findByCertNoAndAcctNoAndInstCode(certNo, acctNo, instCode);
    if (null != sign
            && StringUtils.equals(sign.getStatus(), StatusEnum.SUCCESS.code())
            && DateUtil.getCurrentDate().before(sign.getExpireTime())) {
        return "1";
    } else {
        return "0";
    }
}
}

 

Solution two:

Use @PostConstruct annotation

  • Starting from the Java EE5 specification, two annotations affecting the life cycle of Servlet have been added to Servlet, @PostConstruct and @PreDestroy
  • Explanation of this annotation in Java: @PostConstruct This annotation is under the javax.annotation package and is used to decorate a non-static void() method
  • The method modified by @PostConstruct will run when the server loads the Servlet, and will only be executed once by the server
  • The method modified by @PostConstruct is executed after the constructor, and before the init() method
  • The @PreDestroy() method is executed after the destroy() method is executed
  • @PostConstruct annotation rules: Except for the special case of interceptor, no parameters are allowed in other cases, otherwise the spring framework will report IllegalStateException; and if the return value is void, it can actually have a return value, at least it will not report an error, it will only be ignored
  • Usually we will use the @PostConstruct annotation method in the Spring framework to annotate the execution order of the annotation method in the entire Bean initialization: Constructor (construction method) -> @Autowired (dependency injection) -> @PostConstruct (annotated method)

                                                                   

@Component
public class ScriptExecuteContent {

@Autowired
private SignRepository signRepository;

private static ScriptExecuteContent scriptExecuteContent;

@PostConstruct
public void update() {
    scriptExecuteContent = this;
    scriptExecuteContent.signRepository = this.signRepository;
}

public static String checkSign(String certNo, String acctNo, String instCode) {
    Sign sign = scriptExecuteContent.signRepository.findByCertNoAndAcctNoAndInstCode(certNo, acctNo, instCode);
    if (null != sign
            && StringUtils.equals(sign.getStatus(), StatusEnum.SUCCESS.code())
            && DateUtil.getCurrentDate().before(sign.getExpireTime())) {
        return "1";
    } else {
        return "0";
    }
}
}

Example 2:

@Component
public class StaticBook {
    private static String url;

    @Value("${test.str}")
    private String str;

    @PostConstruct
    public void update() {
        this.url = this.str;
    }

    public static BookTestTemp getValue(){
        return new BookTestTemp(1, "bookName", "123", url);
    }
}

 

Guess you like

Origin blog.csdn.net/xiangwang2016/article/details/106148880