Spring依赖@PostConstruct

时间:2015-06-25 20:19:08

标签: java spring spring-java-config

假设我在Spring @Configuration中有这种依赖关系:

@Bean
public SomeClass someClass(SomeClass1 someClass1, SomeClass2 someClass2, ...) {
  return new SomeClass(someClass1, someClass2, ...);
}

说我想在@PostConstruct中做一些包含someClass依赖的事情:

@PostConstruct
public void init() {
  someClass.doSomething();
}

这不能注入:

@PostConstruct
public void init(SomeClass someClass) {
  someClass.doSomething();
}

导致:

Caused by: java.lang.IllegalStateException: Lifecycle method annotation requires a no-arg method: ...

这不能在同一个配置中自动装配:

@Autowire
private SomeClass someClass;

@Bean
public SomeClass someClass(SomeClass1 someClass1, SomeClass2 someClass2, ...) {
  return new SomeClass(someClass1, someClass2, ...);
}

因为这导致:

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'globalBus': Requested bean is currently in creation: Is there an unresolvable circular reference?

配置可以拆分(所以@Bean转到另一个配置)和@Import - 由此编辑,它可以正常工作。可能存在其他溶剂 - 例如创建一个单独的初始化bean。

有没有办法在一个@Configuration内执行此操作?

修改

根据@SotiriosDelimanolis的要求,使用@Autowired时出现sscce例外:

public class ConfigPostConstructDependenciesPrb {
   public static void main(String[] args) {
      AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
      ctx.getBean(Service.class);
      ctx.close();
   }

   public static class Service {
      private final Dependency dependency;

      public Service(Dependency dependency) {
         this.dependency = dependency;
      }

      public void work() {
         System.out.println(dependency.getNum());
      }

      @Override
      public String toString() {
         StringBuilder sb = new StringBuilder();
         sb.append("Service [dependency=");
         sb.append(dependency);
         sb.append("]");
         return sb.toString();
      }
   }

   public static class Dependency {
      private final int num;

      public Dependency(int num) {
         this.num = num;
      }

      public int getNum() {
         return this.num;
      }

      @Override
      public String toString() {
         StringBuilder sb = new StringBuilder();
         sb.append("SomeClass1 [num=");
         sb.append(num);
         sb.append("]");
         return sb.toString();
      }
   }

   @Configuration
   public static class BaseConfig {
      @Autowired
      private Service service;

      @Bean
      public Dependency dependency() {
         return new Dependency(42);
      }

      @Bean
      public Service service(Dependency dependency) {
         return new Service(dependency);
      }

      @PostConstruct
      public void init() {
         service.work();
      }
   }

   @Configuration
   @Import(BaseConfig.class)
   public static class Config {
      @Autowired
      private Service service;
   }   
}

2 个答案:

答案 0 :(得分:0)

尝试这种方式:

public class ConfigPostConstructDependenciesPrb  {

    public static void main(String[] args) {
        try {
            AnnotationConfigApplicationContext ctx =
                new AnnotationConfigApplicationContext(BaseConfig.class);

            ctx.registerShutdownHook();
            ctx.getBean(Service.class);
            ctx.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}

@Configuration
class BaseConfig {

    @Autowired
    private Service service;

    @Bean
    public Dependency dependency() {
        return new Dependency(42);
    }

    @Bean
    public Service service(Dependency dependency) {
        return new Service(dependency);
    }

    @PostConstruct
    public void init() {
        this.service.work();
    }
}

class Dependency {

    private int num;

    public Dependency() {

    }

    public Dependency(int num) {
        this.num = num;
    }

    public int getNum() {
        return this.num;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("SomeClass1 [num=");
        sb.append(num);
        sb.append("]");
        return sb.toString();
    }
}

class Service {

    private Dependency dependency;

    public Service() {

    }

    public Service(Dependency dependency) {
        this.dependency = dependency;
    }

    public void work() {
        System.out.println(dependency.getNum());
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Service [dependency=");
        sb.append(dependency);
        sb.append("]");
        return sb.toString();
    }
}

答案 1 :(得分:0)

(在Spring 4.3.6中测试)

在@Configuration中创建一个嵌套类,并在其中放置@Autowired service@PostConstruct init()的声明:

@Configuration
public static class BaseConfig {

    //...

    @Bean
    public Service service(Dependency dependency) {
        return new Service(dependency);
    }

    @Configuration
    public static class Setup {

        @Autowired
        private Service service;

        @PostConstruct
        public void init() {
            service.work();
        }
    }
}

下面是相应的完整示例。

请注意,您不必添加对BaseConfig.Setup的显式引用(请查看@Import类之前的Config注释-它仅引用BaseConfig本身)。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.*;

import javax.annotation.PostConstruct;

public class ConfigPostConstructDependenciesPrb {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
        ctx.getBean(Service.class);
        ctx.close();
    }

    public static class Service {
        private final Dependency dependency;

        public Service(Dependency dependency) {
            this.dependency = dependency;
        }

        public void work() {
            System.out.println(dependency.getNum());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("Service [dependency=");
            sb.append(dependency);
            sb.append("]");
            return sb.toString();
        }
    }

    public static class Dependency {
        private final int num;

        public Dependency(int num) {
            this.num = num;
        }

        public int getNum() {
            return this.num;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("SomeClass1 [num=");
            sb.append(num);
            sb.append("]");
            return sb.toString();
        }
    }

    @Configuration
    public static class BaseConfig {
        @Bean
        public Dependency dependency() {
            return new Dependency(42);
        }

        @Bean
        public Service service(Dependency dependency) {
            return new Service(dependency);
        }

        @Configuration
        public static class Setup {
            @Autowired
            private Service service;

            @PostConstruct
            public void init() {
                service.work();
            }
        }
    }

    @Configuration
    @Import(BaseConfig.class)
    public static class Config {
        @Autowired
        private Service service;
    }
}