Reputation: 7226
If I'm writing a static factory method to create objects, how do I use the '@Component' annotation for that factory class and indicate (with some annotation) the static factory method which should be called to create beans of that class? Following is the pseudo-code of what I mean:
@Component
class MyStaticFactory
{
@<some-annotation>
public static MyObject getObject()
{
// code to create/return the instance
}
}
Upvotes: 17
Views: 17255
Reputation: 344
Spring boot:static factory method:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
enum ParsersConst {
bofa, jpm, wellsforgo
}
interface Parser {
String readFromFile(String file);
}
class JPM implements Parser {
@Override
public String readFromFile(String file) {
System.out.println("From JPM Parser");
return "JPM";
}
}
class Bofa implements Parser {
@Override
public String readFromFile(String file) {
System.out.println("From Bofa Parser");
return "BOFA";
}
}
class WellsForgo implements Parser {
@Override
public String readFromFile(String file) {
System.out.println("From Wellsforgo Parser");
return "WellsForgo";
}
}
class ParserCreator {
public static Parser createParser(ParsersConst parsConst) {
if (ParsersConst.bofa.equals(parsConst)) {
return new Bofa();
} else if (ParsersConst.jpm.equals(parsConst)) {
return new JPM();
} else if (ParsersConst.wellsforgo.equals(parsConst)) {
return new WellsForgo();
}
throw new IllegalArgumentException("Unknown Parser");
}
}
@Configuration
class ParserConfig{
@Bean
public Parser bofa() {
return ParserCreator.createParser(ParsersConst.bofa);
}
@Bean
public Parser wellsforgo() {
return ParserCreator.createParser(ParsersConst.wellsforgo);
}
@Bean
public Parser jpm() {
return ParserCreator.createParser(ParsersConst.jpm);
}
}
@Component
public class StaticFacotryDemo implements CommandLineRunner{
@Autowired
private ApplicationContext context;
@Override
public void run(String... args) throws Exception {
Parser parser = (Parser) context.getBean(ParsersConst.jpm.toString());
System.out.println(parser);
System.out.println(parser.readFromFile("jan_stmt.pdf"));
}
}
Upvotes: 1
Reputation: 101
You need to use the spring interface FactoryBean
.
Interface to be implemented by objects used within a
BeanFactory
which are themselves factories. If a bean implements this interface, it is used as a factory for an object to expose, not directly as a bean instance that will be exposed itself.
Implement the interface and declare a bean for it. For example :
@Component
class MyStaticFactoryFactoryBean implements FactoryBean<MyStaticFactory>
{
public MyStaticFactory getObject()
MyStaticFactory.getObject();
}
public Class<?> getObjectType() {
return MyStaticFactory.class;
}
public boolean isSingleton() {
return true;
}
}
Through @Component
and component scanning, this class will be discovered. Spring will detect that it is a FactoryBean
and expose the object you return from getObject
as a bean (singleton if you specify it).
Alternatively, you can provide a @Bean
or <bean>
declaration for this FactoryBean
class.
Upvotes: 7
Reputation: 21
Bean:
public class MyObject {
private String a;
public MyObject(String a) {
this.a = a;
}
@Override
public String toString() {
return a;
}
}
FactoryBean:
@Component
public class MyStaticFactory implements FactoryBean<MyObject> {
@Override
public MyObject getObject() throws Exception {
return new MyObject("StaticFactory");
}
@Override
public Class<?> getObjectType() {
return MyObject.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
Use:
@Component
public class SomeClass{
@Autowired
MyObject myObject;
}
Upvotes: 1
Reputation: 340743
I am afraid you can't do this currently. However it is pretty simple with Java Configuration:
@Configuration
public class Conf {
@Bean
public MyObject myObject() {
return MyStaticFactory.getObject()
}
}
In this case MyStaticFactory
does not require any Spring annotations. And of course you can use good ol' XML instead.
Upvotes: 17