71

I want to inject an ApplicationContext itself to a bean.

Something like

public void setApplicationContext(ApplicationContect context) {
  this.context = context;
}

Is that possible in spring?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
mibutec
  • 2,929
  • 6
  • 27
  • 39

5 Answers5

142

Previous comments are ok, but I usually prefer:

@Autowired private ApplicationContext applicationContext;
sinuhepop
  • 20,010
  • 17
  • 72
  • 107
  • 4
    +1 Btw, do you have any idea about pros cons between injecting applicationContext by directly @Autowired or implementing ApplicationContextAware interface? Thanks. – javatar Mar 11 '12 at 18:58
  • 9
    @Bariscan: I think there are no pros and cons. But I prefer this because @ Autowired is what I use for injecting all properties, so whay to do it differently just beacuse is an ApplicationContext? – sinuhepop Mar 11 '12 at 23:02
  • 1
    Can you provide a more detailed example of @Autowired (I'm a big fan) Application context? It is always null for me. Any extra interfaces needed? Thx. – Joseph Lust Mar 26 '12 at 21:53
  • Is @Autowired injecting other properties in same bean? The exact same code works for me in Spring 3.1.1. – sinuhepop Mar 27 '12 at 08:20
  • 4
    While I agree that `@Autowired` is nice; The difference between using `@Autowired` and ApplicationContextAware can be astonishing when circular references are involved. It turned out that simply removing `@Autowired` solved the issue I described in [circular-dependency-in-spring](http://stackoverflow.com/questions/3485347/circular-dependency-in-spring/17111644#17111644) – jontejj Jun 17 '13 at 10:54
44

Easy, using the ApplicationContextAware interface.

public class A implements ApplicationContextAware {
  private ApplicationContext context;

  public void setApplicationContext(ApplicationContext context) {
      this.context = context;
  }
}

Then in your actual applicationContext you only need to reference your bean.

<bean id="a" class="com.company.A" />
Sergii Shevchyk
  • 38,716
  • 12
  • 50
  • 61
Johan Sjöberg
  • 47,929
  • 21
  • 130
  • 148
13

Yes, just implement the ApplicationContextAware -interface.

esaj
  • 15,875
  • 5
  • 38
  • 52
3

I saw some comments above about @Autowired not working still. The following may help.

This will not work:

@Route(value = "content", layout = MainView.class)
public class MyLayout extends VerticalLayout implements RouterLayout {

  @Autowired private ApplicationContext context;

   public MyLayout() {
    comps.add(context.getBean(MyComponentA.class)); // context always null :(
}

You must do this:

 @Autowired
  public MyLayout(ApplicationContext context) {
    comps.add(context.getBean(MyComponentA.class)); //context is set :)
}

or this:


@PostConstruct
    private void init() {
    comps.add(context.getBean(MyComponentA.class)); // context is set :)
}

Also note that Upload is another component that must be set within the scope of @PostConstruct. This was a nightmare for me to figure out. Hope this helps!

I almost forgot to mention that the @Scope annotation may be necessary for your Bean, as seen below. This was the case when using Upload within a Bean because the UI is not instantiate/attached prior to the Bean being created and will cause a Null Reference Exception to be thrown. It won't do so when using @Route, but will when using @Component - so the latter is not an option and if @Route is not viable, then I would recommend using @Configuration class to create the bean with the prototype scope.

@Configuration
public class MyConfig {
  @Bean
  @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
  public MyComponentA getMyBean() {
    return new MyComponentA();
  }
}
2

Special solution: get Spring beans from any (non Spring) classes

@Component
public class SpringContext {
    private static ApplicationContext applicationContext;

    @Autowired
    private void setApplicationContext(ApplicationContext ctx) {
        applicationContext = ctx;
    }

    public static <T> T getBean(Class<T> componentClass) {
        return applicationContext.getBean(componentClass);
    }
}
Grigory Kislin
  • 16,647
  • 10
  • 125
  • 197