I have a factory class that should return me an instance of classA or classB. These classes implement interface XYZ:
interface xyz;
getInstance()
#service
classA implements xyz{
public void checkStatus(){
}
}
#service classB implements xyz{
public void checkStatus(){
}
}
Factory class:
#component
class ABCFactory{
#Autowire classA A;
public static getInstance(str a){
return classA;
}
}
Client code:
Class A a = ABCFactory.getInstance("A");
a.checkStatus();
I get null pointer exception -- probably a is returned as null?
What is the best approach to implement the factory pattern with spring annotation and autowired bean?
It's difficult to say with any certainty why your auto-wiring isn't taking place without seeing your Spring config. My first guess is that you don't have component scanning switched on:
<context:component-scan base-package="org.example"/>
Adding something like that to your spring config file (with the correct package) will tell Spring to scan the package structure for fields that need to be auto-wired, and services that can be used for auto-wiring.
static is the root of all evil. How did you managed to access classA here?
#Component
class ABCFactory{
#Autowire classA A;
public static getInstance(str a){
return classA;
}
}
A field is not static while getInstance() method is - your code won't compile.
Furthermore, dependency injection works on instances, not on static classes. Thus you should get rid of static:
#Component
class ABCFactory {
#Autowire classA A;
public xyz getInstance(str a){
return A;
}
}
and inject ABCFactory where you need it (e.g. in other services or controllers):
#Autowired
private ABCFactory factory;
BTW your design looks supicious in Spring environment, what do you want to achieve?
Related
In an Spring mockmvc test I want to replace a bean by a mock implementation which is configured using Mockito.when() definitions. The definitions are indeed respected at the time the mock is configured, as well as at the time the mock is injected into a depending bean (a controller advice in my case) during application context startup. However, when the mock is used during a certain test, all when definitions are gone.
Why?
Some remarks:
The mock is completely new code, so it is impossible that I am not aware of any call to Mockito.reset().
the mock at the time of usage is the same as at the time of creation.
a bypassing solution to the problem is to configure the mock in a #BeforeEach method in AbstractTest. However, I want to understand why it does not work without.
Here a simplified and anonymized example
#Component
public class MyBean {
private String property;
...
public String getProperty() {
return property;
}
}
#ControllerAdvice
public class MyControllerAdvice() {
private MyBean myBean;
#Autowired
public MyControllerAdvice(MyBean myBean) {
this.myBean = myBean;
System.out.println(this.myBean.getProperty()); // --> outputs "FOOBAR"
}
#ModelAttribute
public String getMyBeanProperty() {
return myBean.getProperty(); // --> returns null
}
}
public class AbstractTest {
#Configuration
static class Config {
#Bean
public MyBean () {
MyBean myBean = Mockito.mock(MyBean.class, "I am a mock of MyBean");
when(myBean.getProperty()).thenReturn("FOOBAR");
}
}
}
That's not a problem of Mockito. I think you simplified the example a lot and we don't see the full picture, but I can say that main cause - 2 different beans MyBean: one is initialized with Spring's #Component, second is in configuration class with #Bean.
Why do you use #Component for POJO/DO?
#Bean in the configuration class is being initialized lazy so better way to use #PostConstruct
If you want to leave both beans mark MyBean in the configuration class as #Primary
I have the following components, in two different files:
#Component
public class Chauffeur {
Car car;
public Chauffeur(Car car){
this.car = car;
}
public void go(){
System.out.println("Chauffeur");
car.drive();
}
}
#Component
public class Car{
public void drive() {
System.out.println("Drive car");
}
}
the following configuration file:
#Configuration
#ComponentScan
public class DriveableConfiguration {
}
and the following test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=DriveableConfiguration.class)
public class DriveableTest {
#Autowired
Chauffeur chauffeur;
#Test
public void chauffeurTest(){
chauffeur.go();
}
}
All the classes above are in the same package and the test is passing.
In the test I annotated chauffer with #Autowired, which should mean that the Spring container looks after the creation of the instance of Chauffeur without the developer needing to explicitly instantiate it.
Now, the constructor for Chauffer needs an instance of Car, so there is no default constructor for that class. Nonetheless the container creates it, injecting the required instance in the constructor.
Is the #Autowired saying to the container to instantiate the element with whatever (Components, Beans) it can provide, included parameters in the constructor? If so, in what case is it needed to use #Autowired to annotate a constructor?
Only if you use Spring 4.3+. In such a case #Autowired on constructor is optional if you have one non default constructor.
You can check the example here.
So as of 4.3, you no longer need to specify an explicit injection annotation in such a single-constructor scenario. This is particularly elegant for classes which otherwise do not carry any container annotations at all, for example when programmatically registered
For versions lower than 4.3 you will an exception will be thrown:
the container will throw an exception looking for a default
constructor, unless you explicitly indicate autowire mode
‘constructor’ in your bean definition setup (e.g. in an XML )
Following is the code:
public abstract class A {
#Autowired
public Provider provider;
}
#Component
public class B extends A {
B() {
provider.get();
}
}
Spring is throwing NullPointerException, while instantiating Bean of Class B.
I know #Autowired defined in Abstract class are injected, but don't know in which order they are injected.
Earlier my understanding was, While instance creation of B, Spring will autowire fields of all subclasses and then will create instance of B.
But here it seems, it overlooks the subclass concept while instance creation, and just scans B to identify #Autowire field.
Use #PostConstruct. Java Object Instantiation and Spring Dependency Injection are two different flows.
#Component
public class B extends A {
#PostConstruct
void init() {
provider.get();
}
}
If autowiring your constructors is an option the following can be helpful.
public abstract class A {
protected final Provider provider;
#Autowired
public A(Provider provider) {
this.provider = provider;
}
}
#Component
public class B extends A {
#Autowired
B(Provider provider) {
super(provider);
provider.get();
}
}
Note since the latest Spring Versions you do not need to annotate the constructor with #Autowire. If you do things right the spring framework auto-detects the constructor.
I have recently learned concept of autowiring in spring. When I was trying to understand in which particular scenarios spring autowiring can be useful
I came up with the below two reasons from one of the questions asked in our stakoverflow forum.
1.I wanted to read values from a property file and inject them into a bean. Only way I could figure out how to do this at start up of my app was to
wire the bean in XML (and inject the properties.) I ended up using the "byName" attribute (because the bean was also marked as #Component) and then
used #Autowired #Qualifier("nameIChose") when injecting the bean into another class. It's the only bean I've written that I wire with XML.
2.I've found autowiring useful in cases where I've had a factory bean making another bean (whose implementation class name was described in a system
property,so I couldn't define the all wiring in XML). I usually prefer to make my wiring explicit though;
Can any body please give me some code snippet example of the above situations that would make my understanding of autowiring more clearer?
Here is an example of injecting properties into a bean.
Using field injection:
#Component
public class YourBean {
#Value("${your.property.name}")
private String yourProperty;
}
Using constructor injection:
#Component
public class YourBean2 {
private String yourProperty;
#Autowired
public YourBeans2(#Value("${your.property.name}") String yourProperty) {
this.yourProperty = yourProperty;
}
}
The following is a super simple example of autowiring various beans
#Component
public class Foo {
public void doSomething() {
}
}
#Component
public class Bar {
private Foo foo;
#Autowired
public Bar(Foo foo) {
this.foo = foo;
}
public void doSomethingElse() {
foo.doSomething();
}
}
In the previous example, no XML configuration of Foo and Bar needs to be done, Spring automatically picks up the beans because of their #Component annotation (assuming of course that component scanning has been enabled)
I have a requirement of creating a prototype bean that's stateful, i.e. take parameters in constructor.
I tried to use #Configuration to create that bean, but found it doesn't work if I use a parameterized constructor...
Note that the parameters I want to pass are NOT spring beans...they are simple POJOs...so I can't autowire them.
So this is what I want to do -
#Configuration
public class MyClassFactory {
#Bean
public MyClass getMyClass(Pojo1 pojo1, Pojo2 pojo2) {
return new MyClass (pojo1, pojo2);
}
}
#Scope("PROTOTYPE")
public class MyClass {
public MyClass(Pojo1 pojo1, Pojo2 pojo2) {
...
}
#Autowired SomeService1 service1;
#Autowired SomeService1 service2;
...
}
Of course I can make MyClass applicationContextAware, and pick up services from it, rather than making it a prototype bean...but was wondering why above pattern is not allowed...