简体   繁体   中英

Spring - Inject fields to bean before it gets @Autowired

In Spring, is there a mechanism or listener to detect when a bean annotated with a specific annotation is getting @Autowired and run some custom logic on it? Something similar to what @ConfigurationProperties already does that automatically injects fields before it gets autowired.

I have a requirement in which I need to inject values to fields of certain beans annotated with @ExampleAnnotation before they get instantiated. Ideally, in this listener, I would:

  1. Ask if current bean being instantiated is annotated with @ExampleAnnotation
  2. If it isn't, return. If it is, I'd use reflection to get the names of the fields from this bean and populate them using a repository.

Is something like this possible?

You can achive it with the following code:

@Component
class MyBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      // Every spring bean will visit here

      // Check for superclasses or interfaces
      if (bean instanceof MyBean) {
        // do your custom logic here
        bean.setXyz(abc);
        return bean;
      }
      // Or check for annotation using applicationContext
      MyAnnotation myAnnotation = this.applicationContext.findAnnotationOnBean(beanName, MyAnnotation.class);
      if (myAnnotation != null) {
        // do your custom logic here
        bean.setXyz(myAnnotation.getAbc());
        return bean;
      }
      return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
      this.applicationContext = applicationContext;
    }

    // Optional part. If you want to use Autowired inside BeanPostProcessors 
    // you can use Lazy annotation. Otherwise they may skip bean processing
    @Lazy
    @Autowired
    public MyBeanPostProcessor(MyLazyAutowiredBean myLazyAutowiredBean) {
    }
}

I guess if it's similar to ConfigurationProperties , then the class ConfigurationPropertiesBindingPostProcessor that binds properties to beans may serve as an example. It implements BeanPostProcessor and does the binding in the postProcessBeforeInitialization method. This method has the following Javadocs:

" Apply this BeanPostProcessor to the given new bean instance before any beaninitialization callbacks (like InitializingBean's afterPropertiesSetor a custom init-method). The bean will already be populated with property values.The returned bean instance may be a wrapper around the original. "

One possible solution is to write a custom setter and annotate it with @Autowired, like this:

@Autowired
public void setExample(Example example)
{

    // Do your stuff here.

    this.example = example;
}

However, I don't recommend this practice of modifying a bean before autowiring since it can lead to poor code mantainability and it may be counter-intuitive for other people that need to work on your code too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM