开发者

Can @Autowire @Service beans but not members of a class instantiated with "new" keyword - even with context scanning configured

开发者 https://www.devze.com 2023-03-29 17:23 出处:网络
I have an app that\'s been working well with @Autowired @Service beans. Now I\'m adding a Validator class which is instantiated in the Controller:

I have an app that's been working well with @Autowired @Service beans.

Now I'm adding a Validator class which is instantiated in the Controller:

BlueValidator validator = new BlueValidator(colors);
validator.validate(colorBlend, bindResult);

In the BlueValidator class I'm trying to @Autowire the blendService which is working as an @Autowired field elsewhere in the app:

public class BlueValidator implements Validator {
@Autowired
private BlendService blendService;
private Colors colors;

But for some reason after instantiating the BlueValidator, I keep getting NullPointerExceptions for the blendService.

Of course I've added the necessary context scanning:

<context:component-scan 
base-package="com.myapp.controllers, com.myapp.services, com.myapp.validators" />

I also tried adding the@Autowired annotation to the constructor but that didn't help:

@Autowired
public BlueValidator(Colors colors) {
    this.colors = colors;
}

Should I just pass the blendService to the BlueValidator and forget about the Autowiring or is there something 开发者_JAVA技巧obvious missing here?


If you just instantiate an object with new, Spring is not involved, so the autowiring won't kick in. Component scanning looks at classes and creates objects from them - it doesn't look at objects you create yourself.

This can be made to work, using Spring's AspectJ support, but it takes some effort.

Otherwise, you need to let Spring instantiate your objects if you wan autowiring to work.

Should I just pass the blendService to the BlueValidator and forget about the Autowiring

In your situation, I'd say yes, this is the least effort solution.


When you instantiate objects spring cannot do anything for them, so it does not get the dependencies injected (article).

In your case, you have a couple of options:

  • pass dependencies to the validator from the controller (where you can inject them)
  • make the validator a spring bean and inject it, instead of instantiating it
  • use @Configurable, which, via AspectJ, enables spring injection even in objects created with new


@Autowired is being used by Spring's ApplicationContext to populate those fields on creation. Since the ApplicationContext is not the one creating these beans (you are because of the keyword 'new'), they are not being autowired. You need to pass it in yourself if you are creating it.


Don't create validator manually -- allow to Spring do this work for you:

@Controller
class Controller {

    @Autowired
    BlueValidator validator;

    void doSomething() {
        ...
        validator.validate(colorBlend, bindResult);
        ...
    }

}

Also pay attention that adding package com.myapp.validators to context:scan-packages not enough, you also should annotate your validator class with @Component annotation:

@Component
public class BlueValidator implements Validator {
@Autowired
private BlendService blendService;

(BTW this solution works in my project.)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号