I am wondering what is the current best practice as to the use of factory pattern within the context of Spring framework in using dependency injection. My wonder arises about whether the factory pattern is still relevant nowadays in light of the use of Spring dependency injection. I did some searching and see some past discussion (Dependency Injection vs Factory Pattern) but seem there is different view.
I see in some real life project in using a Map to hold all the beans and rely on autowiring to create those beans. When the bean is needed, it get it via the map using the key.
public abstract class Service {
//some methods
}
#Component
public class serviceA extends Service {
//implementation
}
#Component
public class serviceB extends Service {
//implementation
}
Map<String, Service> services;
But I see there is some difference among the two approaches.
Using the above method, all beans are created on application start up and the creation of object is handled by the framework. It also implies there is only one bean for each type.
While for factory pattern, the factory class creates the object on request. And it can create a new object for each request.
I think a deeper question may be, when Spring framework is used in a project, should it be strived to not create any object inside a class, which means the factory pattern ( or any creational design patterns?) should not be used, as Spring is supposed to be the central handler of the objects dependency ?
The answer to this question can be really deep and broad, I'll try to provide some points that hopefully will help.
First off, spring stores its beans (singletons) in the ApplicationContext. Essentially this is the map you're talking about. In a nutshell, it allows getting the bean by name, type, etc.
ApplicationContext, while being a really important concept, is not the whole Spring, in fact Spring framework allows much more flexibility:
You say, using a map implies that all the beans will be created at the beginning of the application and there is one instance of the bean.
Spring has a concept of Lazy beans, basically supporting a concept of beans being actually created only when they're required for the first time, so Spring supports the "delayed" beans initialization
Spring also allows more than one instance of a bean per type. So this map is more "advanced". For example you can create more than one implementation of the interface and use declare both as beans. As long as you provide enough information about what bean should be injected to the class that might use them (for example with a help of qualifiers suppored in spring), you're good to go. In addition, there are features in spring IoC container that allow injecting all registered implementations of an interface into a list:
interface Foo {}
#Component
class FooImpl1 implements Foo {}
#Component
class FooImpl2 implements Foo {}
class Client {
#Autowired
List<Foo> allFoos;
}
Now you say:
While for factory pattern, the factory class creates the object on request. And it can create a new object for each request.
Actually Spring can create objects per request. Not all beans have to be singletons, in general spring has a concept of scopes for this purposes.
For example, scope prototype means that Spring will create a bean upon each usage. In particular one interesting usage that spring supports in variety of ways is Injecting prototype bean into singleton. Some solutions use exactly like a factory (read about annotation #Lookup others rely on auto-generated proxy in runtime (like javax.inject.Provider). Prototype scope beans are not held in the application context, so here again spring goes beyond a simple map abstraction.
Last feature that you haven't mentioned is that sometimes even for singletons the initialization can be a little bit more complicated then calling a constructor with Parameters. Spring can address that by using Java Configurations:
#Configuration
public class MyConfig {
public SomeComplicatedObject foo(#Value("...") config, Bar bar) {
SomeComplicatedObject obj = new SomeComplicatedObject() // lets pretend this object is from some thirdparty, it only has no-op constructor, and you can't place spring annotations on it (basically you can't change it):
obj.setConfig(config);
obj.setBar(bar);
return obj;
}
}
The method foo here initializes the object SomeComplicatedObject and returns it. This can be used instead of factories to integrate "legacy" code (well, java configurations go way beyond this, but its out of scope for this question).
So bottom line, you Spring as an IoC container can provide many different ways to deal with object creation, in particular it can do everything that factory design pattern offers.
Now, I would like to also refer to your last sentense:
I think a deeper question may be, when Spring framework is used in a project, should it be strived to not create any object inside a class, which means the factory pattern ( or any creational design patterns?) should not be used, as Spring is supposed to be the central handler of the objects dependency ?
Indeed you don't have to use Factory Pattern when using Spring, since (as I hopefully have convinced you) provides everything that factory can do and more.
Also I agree that spring is supposed to be the central handler of the objects dependency (unless there are also parts of the application which are written in a different manner so you have to support both :) )
I don't think we should avoid using "new" altogether, not everything should/can be a bean, but I do see (from my subjective experience, so this is arguable) that you use it much less leaving the creation of most of the objects to Spring.
Should we avoid a usage of any creation design pattern? I don't think so, sometimes you can opt for implementing "builder" design pattern for example, its also a creational pattern but spring doesn't provide a similar abstraction.
I think if your project uses Spring framework you should use it. Although it depends on your project design e.g. You may use creational patterns along side with Spring IoC. e.g when you have abstraction layers not framework dependant (agnostic code)
interface ServiceFactory {
Service create(String type);
}
#Component
class SpringServiceFactory implements ServiceFactory {
#Autowired private ApplicationContext context;
Service create(String type) {
return context.getBean(type)
}
}
I use Factory pattern as well when I refactor legacy not unit testable code which also uses Spring Framework in order to implement unit tests.
// legacy service impossible to mock
class LegacyApiClient implements Closeable {...}
#Component
class LegacyApiClientFactory {
LegacyApiClient create(String endpoint) {
return new LegacyApiClient(endpoint);
}
}
#Component
class OtherService {
private final String endpoint
private final LegacyApiClientFactory factory;
OtherService(#Value("${post.endpoint}") String endpoint,
LegacyApiClientFactory factory) {...}
void doCall {
try (LegacyApiClient client = factory.create(endpoint)) {
client.postSomething();
}
}
}
....
// a random unit test
LegacyApiClient client = mock(LegacyApiClient.class)
LegacyApiClientFactory factory = mock(LegacyApiClientFactory.class)
OtherService service = new OtherService("http://scxsc", factory);
when(factory.create(any())).thenReturn(client)
service.doCall()
....
Related
we use interface for autowiring service into controller
this is for loose coupling , coz the interface can hold object of any of its implementations. so no need to write the implementation name and create tight coupling.
however when we have more than one implementations for an interface, we write the #qualifier .
my question is if we have to write qualifier to tell which implementation needs to be injected, then should we still call it loose coupling??
class ServiceInterface {
interfaceMethod();
}
implementation 1:
#component("service1")
class ServiceImpl1 implements ServiceInterface {
interfacemethod(){
}
}
implementation 2:
#component("service2")
class ServiceImpl2 implements ServiceInterface {
interfaceMethod(){
}
now only instead of directly creating Object of ServiceImpl1() using new
ServiceImpl1 obj = new ServiceImpl1();
we write in
class Controller {
#autowired
#qualifier("service1")
ServiceInterface se;
sc.interfaceMethod();
}
Partially yes, because the component that uses the injected qualified bean still didn't create it or handle its lifecycle.
But indeed using #Qualifier creates some sort of coupling. If you want to avoid this, consider making one of your ServiceInterface beans the primary implementation for the interface annotating its class with #Primary as follows:
#Component
#Primary
class ServiceImpl1 implements ServiceInterface {
interfacemethod(){
}
}
With this, every time you need a ServiceInterface implementation but you don't actually specify which one you want (using #Qualifier) the primary one is injected by Spring.
Even though you are using the #Qualifier annotation you are still using inversion of control to let the framework manage your dependencies.
Furthermore, lets say you wouldn't autowire this implementation but use 'new' to create your object.
When the implementation changes you would need to update all the places where this is created. However, with dependency injection you wouldn't need to do so. Therefore you still have the advantages of dependency injection with regards to loose coupling.
If you would like to have your implementation less coupled with your target class then you could do a few things
Use #Primary for a bean to determine the default implementation.
Autowire your implementations into a List<ServiceInterface>
Use Spring's ObjectFactory to determine which bean to use at runtime
Use Profiles to determine which bean to autowire
Java configuration allows us to manage bean creation within a configuration file. Annotated #Component, #Service classes used with component scanning does the same. However, I'm concerned about using these two mechanisms at the same time.
Should Java configuration and annotated component scans be avoided in the same project? I ask because the result is unclear in the following scenario:
#Configuration
public class MyConfig {
#Bean
public Foo foo() {
return new Foo(500);
}
}
...
#Component
public class Foo {
private int value;
public Foo() {
}
public Foo(int value) {
this.value = value;
}
}
...
public class Consumer {
#Autowired
Foo foo;
...
}
So, in the above situation, will the Consumer get a Foo instance with a 500 value or 0 value? I've tested locally and it appears that the Java configured Foo (with value 500) is created consistently. However, I'm concerned that my testing isn't thorough enough to be conclusive.
What is the real answer? Using both Java config and component scanning on #Component beans of the same type seems like a bad thing.
I think your concern is more like raised by the following use case:
You have a custom spring-starter-library that have its own #Configuration classes and #Bean definitions, BUT if you have #Component/#Service in this library, you will need to explicitly #ComponentScan these packages from your service, since the default #ComponentScan (see #SpringBootApplication) will perform component scanning from the main class, to all sub-packages of your app, BUT not the packages inside the external library. For that purpose, you only need to have #Bean definitions in your external library, and to inject these external configurations via #EnableSomething annotation used on your app's main class (using #Import(YourConfigurationAnnotatedClass.class) OR via using spring.factories in case you always need the external configuration to be used/injected.
Of course, you CAN have #Components in this library, but the explicit usage of #ComponentScan annotation may lead to unintended behaviour in some cases, so I would recommend to avoid that.
So, to answer your question -> You can have both approaches of defining beans, only if they're inside your app, but bean definitions outside your app (e.g. library) should be explicitly defined with #Bean inside a #Configuration class.
It is perfectly valid to have Java configuration and annotated component scans in the same project because they server different purposes.
#Component (#Service,#Repository etc) are used to auto-detect and auto-configure beans.
#Bean annotation is used to explicitly declare a single bean, instead of letting Spring do it automatically.
You can do the following with #Bean. But, this is not possible with #Component
#Bean
public MyService myService(boolean someCondition) {
if(someCondition) {
return new MyServiceImpl1();
}else{
return new MyServiceImpl2();
}
}
Haven't really faced a situation where both Java config and component scanning on the bean of the same type were required.
As per the spring documentation,
To declare a bean, simply annotate a method with the #Bean annotation.
When JavaConfig encounters such a method, it will execute that method
and register the return value as a bean within a BeanFactory. By
default, the bean name will be the same as the method name
So, As per this, it is returning the correct Foo (with value 500).
In general, there is nothing wrong with component scanning and explicit bean definitions in the same application context. I tend to use component scanning where possible, and create the few beans that need more setup with #Bean methods.
There is no upside to include classes in the component scan when you create beans of their type explicitly. Component scanning can easily be targeted at certain classes and packages. If you design your packages accordingly, you can component scan only the packages without "special" bean classes (or else use more advanced filters on scanning).
In a quick look I didn't find any clear information about bean definition precedence in such a case. Typically there is a deterministic and fairly stable order in which these are processed, but if it is not documented it maybe could change in some future Spring version.
Do I use dependency injection in the following example:
#Scope("prototype")
#Component
public class Order{
#Autowired
public Order(User user,List<OrderItem> items,.......){
Now somewhere else:
#Component
public class PersistOrder{
#Autowired
Provider<Order> orderProvider;
public void prepareOrder() {
Order order = orderProvider.get();
AS JSR-330 states, the get() method of Provider returns a new instance of Order, but what objects are passed to the new order's constructor? As you can see the order has its own dependencies that has to be injected before the actual order object is retrieved to the method.
Without DI I simply create all neccessary arguments and pass them to the constructor of the new order. So should I use DI here?
EDIT:
This is what the code would seem without DI:
#Component
public class PersistOrder{
public void prepareOrder() {
User user=userDao.get(userId);
List<OrderItem> orderItems=orderItemDao.getAll(orderItemIds);
Order order = new SmartPhoneOrder(user,orderItems);
As you see I have the ids of user and order items and can get their instances from DAOs. Then I pass these instances to the constructor of a subclass of the Order to get an instance. The process seems very clear to me. I mean how can I do this work with DI so that my code enjoy decoupling between PersistOrder and Order classes? Or using DI in this example makes the logic more complex?
Without dependency injection, domain objects can be considered anaemic, and this is arguably an anti-pattern. You're losing many of the benefits of OO, by having data structures, without associated behaviors. For example, to evaluate Order.isValid() you may need to inject some dependency to perform the validation.
You can get dependency injection on classes outside the context of the Spring container by using:
#Configurable
You then declare the recipe for the bean as a protoype, and Spring will use AOP to swizzle the constructor and look up the required dependencies. . Even though its looking up the dependencies, the net effect for you is dependency injection, because you'd only have to change one line to inject something else that evaluates Order.isValid().
This way when you do new Order, or get it from you persistence factory, it already has the dependencies "injected".
To do this requires aspectJ weaving and not just Proxy/CGLib weaving, which is the default. You can use either runtime weaving with a Java agent or build-time weaving. . . I recommend the former for integration tests and the latter for deployment. . .
Service vs Domain Object:
Now that you have the option of rich domain objects the question becomes where to put stuff. Service vs Entity? My take is that the service should orchestrate a use-case specific process based on reusable domain objects. The service is your non-OO gateway for outside subscribers into you system.
. . Google Spring #Configurable for more information and tutorials on AspectJ-based dependency injection of domain classes.
The short question:
Does Castle Windsor have something similar to Spring.Net's "Lookup Method Injection" that can be configured from XML, which provides the ability to fetch transient instances from the container without the class being aware of the IoC container?
The long question:
I'm a long time Spring/Spring.Net user and I have been experimenting with Castle Windsor, by trying to port a project over to it. Spring.Net has a concept of "Lookup Method Injection" which (from the Spring docs)...
Lookup method injection is the ability of the container to override methods on container managed objects, to return the result of looking up another named object in the container. The lookup typically involves a prototype object as in the scenario described in the preceding section. The Spring framework implements this method injection by a dynamically generating a subclass overriding the method using the classes in the System.Reflection.Emit namespace.
What this means is, If I had the following...
public class SomeTransient
{
// ... I have dependencies that need to be filled by IoC container
}
public class SomeClass
{
public virtual void Work()
{
var o = CreateTransient();
}
public virtual SomeTransient CreateTransient() { }
}
I can instruct Spring to override the CreateTransient method, and have that method return a new container created transient instance (with it's dependencies initialized) each time the method is called.
The unique part of this is, it doesn't require direct links to the Spring Framework (eg. SomeClass doesn't have to implement a specific interface).
Is there something similar in Castle Windsor to accomplish this via XML?
(I will eventually move away from XML config, but at the moment I'm just trying to get it running)
Castle has something better; Typed Factories.
You can also inject even a delegate!
http://stw.castleproject.org/Windsor.Typed-Factory-Facility-delegate-based-factories.ashx
It is better because it does not depend on dynamically generation code, and it looks much more cleaner.
It looks much more cleaner because the class doesn't depend on someone overriding that method. It is impossible to test this class without subclassing.
If you really want to do something like this, i would expect:
public abstract class SomeClass
{
public abstract SomeTransient CreateTransient();
}
but... again it doesn't feel right.
Edit 2
Unity 2 support these kind of delegate factories; you can read more here:
http://www.truewill.net/myblog/index.php/2010/05/06/unity_2_0_combining_injectionfactory_and
thanks to #eiximenis
We have a legacy system where something like a Service Locator is used to instantiate and provide all service objects:
class ServiceLocator {
ServiceA serviceA;
ServiceB serviceB;
public ServiceLocator () {
serviceA = ...;
serviceB = ...;
}
public ServiceA getServiceA() {
return serviceA;
}
public ServiceB getServiceB() {
return serviceB;
}
}
(imagine 70 more fields and getters...)
This object is then passed around from class to class to provide access to the service objects.
It is outside the scope of the project to change this design for existing code, but to at least not make things worse, we would like to introduce Spring to progressively instantiate future services with DI similar to Introducing an IoC Container to Legacy Code.
In contrast to the aforementioned situation, we already know how we will access the spring created spring bean objects from our legacy code. Our problem are objects we plan to create with spring, that need any of the service objects created outside of the spring context.
We came up with the following solution:
Create a static accessor for the ServiceLocator and set it in the constructor, load the spring application context object. In the spring configuration create a bean for the ServiceLocator with the static accessor as described in Section 3.3.2.2 in the Spring reference:
<bean id="serviceLocator"
class="ServiceLocator"
factory-method="getInstance"/>
for each Service create another bean using "instance factory method" as described in Section 3.3.2.3:
<bean id="serviceA"
factory-bean="serviceLocator"
factory-method="getServiceA"/>
Create other beans referencing these "dummy beans".
I guess this would work, but creates a lot of seamingly unnessessary pseudo configuration. What I'd rather like is something like this:
"If a bean is referenced and that bean is not explicitly defined, search for a method with the needed signature and name in the ServiceLocator class and use this object."
Is it possible to do so? Are there any entry points into the spring bean instantiation process that I am not aware of and that can be used here? Can I do this by subclassing the spring application context class?
Any help would be greatly appreciated!
You can define a BeanFactoryPostProcessor to populate your application context with beans from ServiceLocator.
In BeanFactoryPostProcessor, use beanFactory.registerSingleton(...) to add a fully instantiated bean, or ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition(...) to add a definition (note that some application contexts may not implement BeanDefinitionRegistry, though all typical contexts implement it).