Can @Autowire @Service beans but not members of a class instantiated with "new" keyword - even with context scanning configured
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 NullPointerException
s 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 withnew
@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.)
精彩评论