Grails - Best Way to Access Beans in Normal Groovy Classes - performance

I'm trying to inject an existing bean into a Groovy class and I know Grails bean injection doesn't work for normal Groovy classes (in src/groovy folder). I can get access to a bean via
Holders.applicationContext.getBean('beanName')
However, I'm wondering if this is the best approach (from a execution speed and memory usage point of view). I will be calling a bean from a method that's called hundreds of times during the normal use of the application and I'm wondering if there might be a better approach. At the very least, should I be storing the bean reference (maybe in the constructor) so that I don't call the above code over and over again? Could I store a static reference to the bean so that each class doesn't have to store its own? Any other suggestions or improvements?

Your Groovy (or Java) class cannot use dependency injection, but it is very likely called directly or indirectly from a class that can, e.g. a controller or a service. Rather than having this class pull in its dependencies (which runs pretty strongly against the ideas of dependency injection and inversion of control), pass into the class the beans that it needs, or at a minimum the ApplicationContext if the beans aren't always known up front.
So for example rather than doing this in your service (where Thing is your src/groovy class):
def someServiceMethod(...) {
def thing = new Thing()
thing.doSomething(42, true)
}
add a dependency injection for the bean it needs in the service and pass it along with the other args, either in the constructor or in individual methods, e.g.
class MyService {
def someBean
def someServiceMethod(...) {
def thing = new Thing(someBean)
thing.doSomething(42, true)
}
}

Groovy classes in src/groovy are not picked up for dependency injection by default. But you can configure them manually by adding a bean definition to conf/spring/resources.groovy:
import your.class.from.src.groovy.MyBean
beans = {
myBean(MyBean)
}
Using this way you can configure how dependencies should be resolved.
You can do this manual, e.g.
myBean(MyBean) {
myService = ref('myService') // assumes you have a MyService bean that can be injected to the `myService` field
}
Or you can use autowiring (what grails does by default for services/controllers):
myBean(MyBean) { bean ->
bean.autowire = 'byName'
}
By adding beans to resources.groovy you can also inject these beans into services and controllers.
For more details see the Spring section in the Grails documentation

Related

Spring lookup-method and scoped proxy usage

I'm a bit confused about using method injection (lookup-method) and aop scoped-proxy (Since both used for different scoped beans injection) so
1) When to use method injection and when to use aop-scoped proxy ?
2) What is the reason why a aop-scoped proxy will not be used for a prototype bean ?
Both lookup method injection and scoped proxy are means to inject shorter lived beans into longer lived beans. However, they serve different use cases.
Method injection is useful in cases where a singleton-scoped bean has a dependency on a prototype-scoped bean.
A proxy gets injected in place of the desired bean and provides that bean depending on the context. For example, if a singleton bean (such as a Spring MVC controller) auto-wires a session scoped bean, then the proxy delivers that bean belonging to the current HTTP session.
Such a proxy doesn't apply well to a situation where a prototype bean shall be obtained at runtime. Lookup method injection is one way to obtain prototype instances at runtime.
However, method injection has limitations because it builds upon abstract methods. Hence, certain things like writing unit tests are more cumbersome, as you need to provide a stub implementation of the abstract method. Component scanning doesn't work with abstract classes either.
One alternative to method injection is Spring's ObjectFactory, or its JSR equivalent Provider.
Another, straightforward way of creating prototype bean instances at runtime (which even makes it possible to provide constructor arguments) is to implement a bean factory like the following:
#Configuration
public class MyProvider {
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public MyThing create(String name) {
return new MyThing(name);
}
}
Usage:
#Component
public class MySingleton {
#Autowired
private MyProvider myProvider;
public void doStuffThatNeedsAPrototypeBeanInstance() {
MyThing thing = myProvider.create("some name");
...
}
}
For the question 1. When to use method injection and when to use aop-scoped proxy?
Let's say you have a singleton bean A has dependency on the prototype bean B. A has a method m which has B involved.
You got the object a of A and execute the method m several times. Every time m executing, a new object b of B needs to inject to a. That's the time you use the method injection.
Besides, if you have a singleton bean A has dependency on the session bean B. A has a method m which has B involved.
You got the object a of A and execute the method m several times. As long as the execution time is in a same session, a has the same object b of B. That's the time you use proxy.

Java Configuration vs Component Scan Annotations

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.

What is the difference between dependency injection and dependency look up?

What is Dependency look up?Could someone please clarify these two concepts.
Since #Michael Zucchetta explained what is the difference in the context of Spring, I'll try to give you a more general explanation. The main difference between the two approaches is "who is responsible for retrieving the dependencies".
Usually, in DI(dependency injection) your component isn't aware of the DI container and dependencies "automagically" appear (e.g. you just declare some setters/ constructor parameters and the DI container fills them for you).
In, DL (dependency lookup) you have to specifically ask for what you need. What this means in practice is that you have a dependency on the context (in spring the Application context) and retrieve whatever you need from it.
You can take a look at ServiceLocator vs DependencyInjection by M. Fowler for a better explanaition, but I'll give you a quote:
The key difference is that with a Service Locator every user of a service has a dependency to the locator. The locator can hide dependencies to other implementations, but you do need to see the locator. So the decision between locator and injector depends on whether that dependency is a problem.
Using dependency injection can help make it easier to see what the component dependencies are. With dependency injector you can just look at the injection mechanism, such as the constructor, and see the dependencies. With the service locator you have to search the source code for calls to the locator. Modern IDEs with a find references feature make this easier, but it's still not as easy as looking at the constructor or setting methods.
Hope this helps.
Dependency lookup is when the object itself is trying to find a dependency, such as:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/application-context.xml");
MyBean bean = applicationContext.getBean("myBean")
Here, the class itself is initializing the ApplicationContext through an XML, and it is searching in the context for the bean called myBean in the ApplicationContext
The Dependency injection is when a property is automatically bound when an instance is initialized. For example:
in the application-context.xml, we have one line which initialize the bean and another to initialize the object of, let's say, MyClass:
<bean id="myBean" class="org.mypackage.MyBean"/>
<bean id="myClass" class="org.mypackage.MyClass"/>
Then in MyClass, you have something like:
#Component
public class MyClass{
#Autowired
MyBean myBean;
// ...
}
In this case, you have specified that two instances of two beans are initialized. And the myClass bean has a property called myBean which is already initialized due to the injection
Dependency lookup is more traditional approach:
component has to ask for dependency reference from JNDI registry
We can achieve this by the way of two methods:
Dependency Pull
ApplicationContext ctx = new ClassPathXmlApplicationContext("META-INF/spring/app-context.xml");
SimpleBean mr = ctx.getBean("renderer", SimpleBean.class);
Contextualized Dependency Lookup (lookup is pulled from directly from container, not from registry). Component has to implement specific interface in order to be able execute lookup
public interface Container {
Object dependencyLookup(String key);
}
public class CDL implements Container {
private Dependency dependency;
#Override
public void performLookup(Container container) {
this.dependency = (Dependency) container.dependencyLookup("myDependency");
}
}
Dependency injection is more counterintuitive (but more flexible , scalable):
dependencies are injected into component
There are two ways to do this by:
Constructor
Setter Dependency Injection.

Ask Spring for a Prototype instance of a Singleton Bean?

I have a number of Grails Services that are singleton Spring beans, not prototypes.
Is there any way to retrieve a prototype instance (fully injected with any dependencies) of what is normally a singleton bean?
I'd like this for testing purposes so that I can mess with the prototype instance (potentially changing it's metaClass to mock things out) without the risk of forgetting to clean up after any changes I make to the instance and having them leak into other tests.
I've been playing around with this a little bit and haven't had any luck. I've tried doing something like this:
def ctx = grailsApplication.mainContext
ctx.registerPrototype("foo", MyService)
I'm then able to ask Spring for an instance of MyService
def myServicePrototype = ctx.getBean("foo")
and it does give a new instance every time, but none of the instances have had their properties autowired up so they're all null. I'm guessing theres some way to create a BeanDefinition and feed it to the BeanFactory with some of the autowire stuff that I must be missing turned on.
I'm hoping to come up with some generic solution that doesn't force me to explicitly annotate the target services in any way.
Is there any way to directly ask the Spring applicationContext for a prototype version of what's normally a singleton?
Figured out how to do it using the Grails BeanBuilder to create a temporary ApplicationContext that has the main app context as a parent. This won't work if any unusual wiring/spring configuration has been done to the service, but that's not normally the case with Grails services, so seems like a good default pattern:
// this works in the grails console where grailsApplication is in the binding,
// need to inject in other situations
import org.springframework.context.ApplicationContext
import grails.spring.BeanBuilder
import com.example.service.MyService
def getPrototypeInstanceOf(Class clazz) {
BeanBuilder beanBuilder = new BeanBuilder(grailsApplication.mainContext)
String beanName = "prototype${clazz.name}"
beanBuilder.beans {
"$beanName"(clazz) { bean ->
bean.autowire = 'byName'
}
}
ApplicationContext applicationContext = beanBuilder.createApplicationContext()
return applicationContext.getBean(beanName)
}
def prototypeService = getPrototypeInstanceOf(MyService)
def singletonService = grailsApplication.mainContext.getBean("myService")
assert singletonService != prototypeService
assert singletonService.injectedService == prototypeService.injectedService
If it is only for testing purposes and there are no conflicting dependencies (e.g. some beans that must only be singltons), then you can just create your Spring context twice.
EDIT: Another aproach could be that you define a factory interface for your singleton service and provide 2 implementations of that factory interface: 1 for singleton only and second for having multiple instances depending on your testing situation.

Accessing legacy out-of-container instantiated objects from Spring beans

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).

Resources