Original article by jessehzx link to article: portal

The problem

Some tools in the class the static method need to rely on other object instance (the instance has been configured in the XML into beans, not static loading can use the @autowired normal use), and we know that after class loading static members is in Shared memory area, the inside of the static method must use static member variables, it has the following code:

@Component
public class TestClass {

    @Autowired
    private static AutowiredTypeComponent component;

    // Call the static component's methods
    public static void testMethod(a) {
        component.callTestMethod();
    }
    
}
Copy the code

Java compilation is normal, but running times. Lang. NullPointerException: null abnormalities, clearly in the call testMethod () method, the component variables has not been initialized, the NPE.

why

In the Spring Framework, we cannot @autowired a static variable to make it a Spring bean. Why is that? This is simple because the Spring context has not yet been loaded when the class loader loads the static variable. So the classloader will not inject static classes correctly into the bean and will fail.

The solution

  • Methods a

Annotate @AutoWired to the class constructor. Spring scans the bean for AutowiredTypeComponent and assigns it to the static component variable. The following is an example:

@Component
public class TestClass {

    private static AutowiredTypeComponent component;

    @Autowired
    public TestClass(AutowiredTypeComponent component) {
        TestClass.component = component;
    }

    // Call the static component's methods
    public static void testMethod(a) {
        component.callTestMethod();
    }
    
}
Copy the code
  • Way 2

Add setter methods to static components and append @autoWired to this method. Spring can scan for AutowiredTypeComponent beans and inject them through setter methods. The following is an example:

@Component
public class TestClass {

    private static AutowiredTypeComponent component;

    @Autowired
    public void setComponent(AutowiredTypeComponent component){
        TestClass.component = component;
    }
    
    // Call the static component's methods
    public static void testMethod(a) {
        component.callTestMethod();
    }
    
}
Copy the code
  • Methods three

Define a static component, define a non-static component annotated with @AutoWired, and define a method that initializes the component annotated with @postConstruct. This annotation was introduced by JavaEE as an annotation for the life cycle of servlets. All you need to know is that methods annotated with it will be called after the constructor. The following is an example:

@Component
public class TestClass {

   private static AutowiredTypeComponent component;

   @Autowired
   private AutowiredTypeComponent autowiredComponent;

   @PostConstruct
   private void beforeInit(a) {
      component = this.autowiredComponent;
   }
   
   // Call the static component's methods
   public static void testMethod(a) { component.callTestMethod(); }}Copy the code
  • Methods four

Get the bean directly with the Spring Framework utility class and define it as a local variable to use. The downside is that if you have multiple static methods in the class that use the component multiple times, you need to get it this way each time, and I personally don’t recommend this. The following is an example:

public class TestClass {
    
    // Call the static component's methods
   public static void testMethod(a) {
      AutowiredTypeComponent component = SpringApplicationContextUtil.getBean("component"); component.callTestMethod(); }}Copy the code

conclusion

  • In the above code example, I annotated each class with @Component, which could be changed if needed. For example, this class handles business logic and could be replaced with @service. This class handles requests for forwarding or redirecting, and can be replaced with @Controller (a spring-MVC annotation); This class is specifically used to manipulate Dao’s @repository. Spring’s annotations help you do one interesting thing: they layer your application so that you can separate request handling, business logic handling, and database operation handling, which decouples your code and makes it easier to develop and maintain your project.
  • The Spring container bean loading mechanism uses Java reflection, which I won’t cover here; I’ll write a future article summarizing the use of Java reflection in Spring’s IoC and AoP.