1. Overview

Spring provides some special interfaces so that a bean implementing such an interface gets called during the application startup.

In this tutorial, we'll investigate the Spring's Aware interfaces.

2. Aware Interfaces

Let's start with the Aware interface and its subinterfaces:

public interface Aware {
}

As we can see, Aware is just a marker interface. However, its subinterfaces have methods which we can use.

2.1. Using ApplicationContextAware

Firstly, let's look at the ApplicationContextAware interface.

The ApplicationContextAware interface has the setApplicationContext(ApplicationContext applicationContext) method. So we can use it to access the ApplicationContext bean:

@Component
public class LoggerService implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

Here, Spring calls the setApplicationContext() method after it creates the LoggerService bean.

Although this is a valid approach, it couples the code with Spring related classes. Alternatively, we can use the @Autowired annotation to inject the ApplicationContext bean.

2.2. Using EnvironmentAware

Secondly, we'll investigate the EnvironmentAware interface which has the setEnvironment(Environment environment) method:

@Component
public class LoggerService implements EnvironmentAware {

    private Environment environment;

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}

Here, Spring calls the setEnvironment() method after the LoggerService bean is created.

In addition to ApplicationContextAware and EnvironmentAware, there are also other Aware interfaces which Spring provides.

3. Implementing a Custom Aware Interface

Now, we'll continue with implementing our own Aware interface.

We'll first define our interface:

public interface ActiveProfilesAware extends Aware {

    void setActiveProfiles(List<String> activeProfiles);
}

In the end, our ActiveProfilesAware interface will set the active profiles to the implementing bean.

Secondly, we'll create a bean implementing ActiveProfilesAware:

@Component
public class PersonService implements ActiveProfilesAware {

    private List<String> activeProfiles;

    @Override
    public void setActiveProfiles(List<String> activeProfiles) {
        this.activeProfiles = activeProfiles;
    }
}

Lastly, we should have a BeanPostProcessor to process the beans implementing ActiveProfilesAware:

@Component
public class ActiveProfilesPostProcessor implements BeanPostProcessor {

    private final Environment environment;

    @Autowired
    public ActiveProfilesPostProcessor(Environment environment) {
        this.environment = environment;
    }

    @Nullable
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof ActiveProfilesAware) {
            List<String> activeProfiles = Arrays.stream(environment.getActiveProfiles()).collect(Collectors.toList());
            ((ActiveProfilesAware) bean).setActiveProfiles(activeProfiles);
            return bean;
        }

        return bean;
    }
}

After this setup, Spring will call the setActiveProfiles() method on beans implementing ActiveProfilesAware.

4. Summary

In this tutorial, we've investigated Spring's Aware interfaces. Additionally, we've learned how to implement our own Aware interface.

Finally, check out the source code over on Github.