Spring prototype following prototype design pattern - spring

Spring provides bean scope as "Prototype". Means whenever bean is required in application, Spring container will create a fresh/new instance of bean.
Does is follow prototype design pattern also?
Does it create object only once and in subsequent request calls clone() method on created object to create new object?
Also if someone can provide example of prototype in JDK, Spring, Hibernate or any J2EE framework.

No spring does not use cloning to create prototype scoped instances.
Below is the code snippet taken from AbstractBeanFactory.doGetBean() function:
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
#Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
The createBean method call boils down to below code:
BeanUtils.instantiateClass(constructorToUse);

Spring does not use the Prototype Pattern, it uses reflection.
Plus, in order to use clone() it would have to subclass somehow a bean, because clone() is protected, so it does not use clone() either.
Here is a code fragment from
org.springframework.beans.factory.support.SimpleInstantiationStrategy
where you can see the use of java.lang.reflect.Constructor and java.lang.Class reflection method:
public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
if (beanDefinition.getMethodOverrides().isEmpty()) {
Constructor<?> constructorToUse;
synchronized (beanDefinition.constructorArgumentLock) {
constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
...
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
...
}
...
}
...
}
So the term prototype is used to suggest that at every call to getBean, you'll get a new instance with the same properties. This is more than a simple call to a constructor however, because you'll get a bean with all dependencies wired and other properties set, so in a sense it is a prototype. Or at least it fits the concept very well.

I have not dug into Spring source code, but I think Beans with prototype scope in Spring are not created using clone() method because it is not mandatory to implement the Cloneable interface for those beans.
Moreover, suppose it is creating them using clone(). It would then be dangerous if someone is expecting deep copy instead of shallow copy.
You can always test it and find the answer.

No. Spring scopes such as prototype or singletone do not follow strictly design patterns. The naming of scopes was used to intuitively suggest behavior container provides.
This way you can have a "singleton" pattern within the container and create another object outside of the container. Similarly "prototype" pattern does not have to implement "clone" functionality.
You may want to look into this link as well: Singleton design pattern vs Singleton beans in Spring container
More elaborate explanations here:
https://springframework.guru/gang-of-four-design-patterns/prototype-pattern/

Related

Spring - Retrieve all scanned packages

I'm creating a Spring Starter project and need to get all classes which are marked with a custom annotation. The annotated class is not a spring bean.
My current solution is to use the ClassPathScanningCandidateComponentProvider to find the required classes.
ClassPathScanningCandidateComponentProvider scanner =
new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(CustomAnnotation.class));
candidates = scanner.findCandidateComponents("THE MISSING PACKAGE NAME");
The problem is that I'm currently provide an empty package String so that all packages/classes are scanned which slows the startup down.
I need to access the packages which are scanned by Spring to avoid the scanning of all packages and classes.
Is there a way to retrieve all packages programmatically which are scanned by Spring or is there an alternative solution to retrieve custom annotated classes which are not Spring beans.
Greets
One solution without the need to make a full classpath scan is to use the AutowiredAnnotationBeanPostProcessor:
private List<Class<?>> candidates = new ArrayList<>();
#Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if(beanClass.isAnnotationPresent(YourAnnotation.class)){
candiates.add(beanClass));
System.out.println(beanClass);
return new Object();
}
}
#Bean
public CandiateHolder candidates() {
return new CandidateHolder(candidates);
}
You can check if the bean class which should be instantiated has the required annotation. If its the case you add the class to a property to expose it later as a bean. Instead of returning null you have to return an instance of a new Object. The returned object can be used to wrap the class in a proxy. Cause I don't need an instance I will return a simple new object. Its maybe a dirty hack but it works.
I have to use this kind of hack cause an instantiation of the needed object will result in an runtime error cause it has to be instantiated in the framework I use.

Spring constructor injection with FXML

I have searched for the answer, but i could not found too much.
What i have found: http://steveonjava.com/javafx-in-spring-day-2/
That is a good post about how to use spring for controllers, but it say that you cannot use constructor injection. That would not be so big pain, it is just not so clean for me.
The issue come up when i would like to use custom controls (or custom components). Custom controls are created by javafx so that will not be in spring context.
The issue is that with the given solution only the controllers will be created by spring. I have found a possible way that can be done. thanks to https://www.javacodegeeks.com/2012/04/fxml-custom-components-using.html articel. But i would like to generalize that solution. So the plan is to write my custom BuilderFactory and Builder implementations, which is required a lot of reflection.
What do you think about this approach?
Every idea is welcome
You can certainly use a BuilderFactory to do this. The code is not too bad at all, because the default builder factory is implemented in public API as JavaFXBuilderFactory. Thus you can simply delegate to that if there is no bean of the appropriate type in the application context.
Basically:
private Parent loadFXML(ApplicationContext applicationContext, URL fxmlLocation)
throws IOException {
FXMLLoader loader = new FXMLLoader(fxmlLocation);
// load controllers from application context:
loader.setControllerFactory(applicationContext::getBean);
// load controls from application context, where available:
loader.setBuilderFactory(new BuilderFactory() {
JavaFXBuilderFactory defaultFactory = new JavaFXBuilderFactory();
#Override
public javafx.util.Builder<?> getBuilder(Class<?> type) {
String[] beanNames = applicationContext.getBeanNamesForType(type);
if (beanNames.length == 1) {
return new javafx.util.Builder<Object>() {
#Override
public Object build() {
return applicationContext.getBean(beanNames[0]);
}
};
} else {
return defaultFactory.getBuilder(type) ;
}
}
});
return loader.load();
}

How to 'get' the spring prototype beans cleanly?

I would like my other classes to interact with my domain's interfaces rather than implementation, and i would like to avoid hardcoding the implementation in the code, such as this example :
public void addToMyList(String s, int i) {
DomainModel model = new DefaultDomainModelImpl(); // it's hardcoding the implementation here
model.setName(s).setAge(i);
myList.add(model);
}
If i use spring container, with the prototype scope, i can use something like :
// <bean id="myDomainBean" scope="prototype" class="my.package.domain.MyDomainImpl" />
DomainModel myDomainModel = springContext.getBean("myDomainBean");
But i would like to avoid accessing springContext explicitly in my code.
I wonder what's the clean way to do this ?
Im currently thinking of creating a factory implementation for each domain implementation, and autowire the factory to create the beans, but that means different implementations of my domain will have different implementations of the factory also.
Please share your opinions, thank you !
Im currently thinking of creating a factory implementation for each domain implementation, and autowire the factory to create the beans, but that means different implementations of my domain will have different implementations of the factory also.
That is not 100% correct. You can have a factory that take the Interface (class) of the Domain objects that needs to be create. You can inject that factory in you class.
So you will get all the requriements you asked for:
no hard coded new
the domain object code has no dependence to spring
you only have one factory class and one factory method.
example
#Inject
MyStrangeSpringHiddingFactory myStrangeSpringHiddingFactory;
DomainModel myDomainModel = this.myStrangeSpringHiddingFactory.
createInstanceOf(DomainModel.class);
class MyStrangeSpringHiddingFactory implements MyStrangeSpringHiddingFactory {
#Inject
ApplicationContext springContext:
public <T> createInstanceOf(Class<T> clazz) {
return springContext.getBean(clazz);
}
}
This are only my thoughts, because I do not know your use case: Do you really need such in abstraction? Do you really have a domain model where a domain class have several subclasses that need a factory.

Grails Dependency Injection Outside of Services?

I have a Grails application that needs to run a strategy that will likely be swapped out over time. I know Spring underlies Grails, so I was wondering if I had access to Spring's IoC container so that I could externalize the actual dependency in an xml file (note: I have never actually done this, but just know of it, so I may be missing something). My goal is to be able to do something like the following:
class SchemaUpdateService {
public int calculateSomething(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
IStrategy strat = (IStrategy) ctx.getBean("mystrat");
}
}
And then map the appropriate implementation in the beans.xml file. I assume this is supported in Grails. Does anyone have any documentation on how this would work? Do I really just need the Spring IoC library and it will just work? Thanks!
You define your beans in resources.xml or resources.groovy. The grails documentation is very clear about how to access the Spring application context.
You can access the application context from any Grails artefact using
ApplicationContext ctx = grailsApplication.mainContext
You can then use this to retrieve whichever beans you're interested in:
IStrategy strat = (IStrategy) ctx.getBean("mystrat")
In classes that don't have access to grailsApplication, you could use a helper such as the following to access the application context and the beans therein
class SpringUtils {
static getBean(String name) {
applicationContext.getBean(name)
}
static <T> T getBean(String name, Class<T> requiredType) {
applicationContext.getBean(name, requiredType)
}
static ApplicationContext getApplicationContext() {
ApplicationHolder.application.mainContext
}
}
However, this should only be necessary if you need to retrieve different implementations of the same bean at runtime. If the required bean is known at compile-time, just wire the beans together in resources.xml or resources.groovy
First of all, you want to define your strategy in your grails-app/conf/spring/resources.groovy:
beans = {
myStrat(com.yourcompany.StrategyImpl) {
someProperty = someValue
}
}
Then, you simply def the a property with the same name into your service:
class SomeGrailsService {
def myStrat
def someMethod() {
return myStrat.doSomething()
}
}
In any Grails artefact (such as services and domain classes), Grails will automatically give the myStrat property the correct value. But don't forget, in a unit test you'll have to give it a value manually as the auto-wiring does not happen in unit tests.
Outside of a Grails artefact, you can use something like:
def myStrat = ApplicationHolder.application.mainContext.myStrat
In Grails 2.0, Graeme et al are deprecating the use of the *Holder classes (such as ApplicationHolder and ConfigurationHolder), so I'm not quite sure what the Grails 2.0 approach would be...

Where should I instantiate my models in a ColdFusion Model Glue controller?

Let's say I have a client who has a list of orders and a wishlist. In my model, I have a ClientRepo, OrderRepo, and WishListRepo. In the controller, where should I be instantiating these repositories? Is it a good idea to make them class-level instances?
component ClientController
{
ClientRepo = new ClientRepo();
OrderRepo = new OrderRepo();
WishListRepo = new WishListRepo();
public void function HomePage(any event)
{
var clientId = event.getValue("id");
var client = ClientRepo.getClientById(clientId);
var orders = OrderRepo.getOrdersForClientId(clientId);
// put the variables into the event object for the view to access
}
}
Or would a better design be to instantiate them within the function?
public void function HomePage(any event)
{
var ClientRepo = new ClientRepo();
var orderRepo = new OrderRepo();
var wishListRepo = new WishListRepo();
// rest of the code is the same
}
The assumption here is that other functions in ClientController need access to the same repositories.
Also, what is the lifetime of the controller? Is it once-per-request, once-per-session, or once-per-application?
Disclosure: I'm a contributor to the Model-Glue project so I probably know what I'm talking about :-)
CFML doesn't have true class-level instances like Java. If you want singletons (a single instance shared across many parts of an application) you need to either put it in a shared scope (yuk!) or use a bean container. Fortunately Model-Glue has tight integration with ColdSpring (a popular bean container for CFML), and Model-Glue 3 makes it easier than ever to use ColdSpring beans in your controllers.
First, edit your ColdSpring.xml to include definitions for your singletons:
<bean id="ClientRepo" class="MyApp.model.client.ClientRepo"/>
<bean id="OrderRepo" class="MyApp.model.order.OrderRepo"/>
This is only a simple example of course. ColdSpring is a powerful dependency injection framework based on Java's Spring. Check out the ColdSpring Quickstart for some of the other things you can do with it.
Once the beans are defined in ColdSpring, you could have your controller explicitly ask for them via getModelGlue().getBean() calls. However a better way is to declare your controller's dependency on those beans and let Model-Glue inject them into your controller for you. The dependency can be declared either in ModelGlue.xml or in your controller CFC. Here's how to declare bean dependencies in your controller:
component ClientController beans="ClientRepo,OrderRepo"
{
public void function HomePage(any event)
{
var clientId = event.getValue("id");
var client = beans.ClientRepo.getClientById(clientId);
var orders = beans.OrderRepo.getOrdersForClientId(clientId);
// put the variables into the event object for the view to access
}
}
Any declared beans are injected into the "beans" scope of your controller by the framework so they're ready to use by any listener functions. Note however that bean injection occurs after initialization, so you cannot use them an init() function.
ColdSpring beans are singletons by default, so if the same ColdSpring bean is injected into multiple controllers they will all end up with the same instance of the bean. If you add singleton="false" to the bean definition then each controller will each end up with a different instance; I can't think of why you would want to do that though.
For more information on bean injection in Model-Glue, check out the Bean Injection HOWTO on the Model-Glue Wiki.
Model-Glue 3.1 instantiates all its controllers at framework initialization time as singletons, so each controller is created once-per-application. Future versions may delay the instantiating of controllers until they are first needed, so it's best to not make assumptions on when they are initialized. If you really need to have some code in a controller executed on application initialization time, I suggest you add an onApplicationStart listener to it.

Resources