I am using #Configurable beans for non-managed spring instances in a section of code that must be highly performant. We are using a lot of non-managed beans with the new operator, and in our profiling we have noticed that the use of the #Configurable annotation is slowing things down quite a bit.
Just for this specific section, we would like a faster way of pulling beans from the context (just a direct applicationContext.getBean()). I know we give up IoC doing this, but this is a special scenario and not a normal pattern.
We are using CTW for the weaving, but I wanted to know what mechanism spring is using behind the scenes to get the application context so we can simply grab it and use getBean? A static application context? Is it stored in threadlocal somewhere?
Aspects are singletons managed by AspectJ. When you put an aspect in your Spring configuration file Spring doesn't actually create the aspect. Instead it obtains a reference to the aspect using aspectOf().
This means that (at compile time when you do your weaving) your #Configurable annotation gets hooked into the singleton AnnotationBeanConfigurerAspect. Then when you load your application context, Spring obtains a reference to that same singleton aspect and calls the setBeanFactory() method on the aspect (since it implements BeanFactoryAware).
This magic can lead to trouble of course. If you had two application contexts then the second would overwrite the configuration of the first which can be terribly confusing.
To answer your question directly this means that all you have to do is create a new aspect that implements BeanFactoryAware (here is the code for AnnotationBeanConfigurerAspect which you can use as an example) and then "instantiate" that same aspect in your spring configuration file and your aspect will now have access to the bean factory.
If you're going for performance then please note that the above is not much cleaner than creating a static reference to the BeanFactory and instantiating that when you start your application so you might as well do the static reference as it is simpler.
Related
Is it possible to create a Java aspect that runs on class initialization using Spring AOP?
We have an annotation that will be used in several places, and in order to make use of the annotation we need some boilerplate code that needs to run every second (using #Scheduled). We're hoping to move that boilerplate code to another class-level annotation to make it easier to reuse.
As far as I understand, it's not possible to implement such a class-level annotation using Spring AOP since it only supports method execution (https://www.baeldung.com/spring-aop-vs-aspectj#4-joinpoints). Is there any workaround to achieve what we're hoping for? I'm aware we could use AspectJ instead of Spring AOP, but I'm reluctant to do that because it's complex to use.
Code snipped:
#Scheduled(fixedDelayString = "${app.pollable-consumer.time-interval}")
public void pollForDeletionRequest() {
log.trace("Polling for new messages");
cleanupInput.poll(cleanupSubmissionService::submitDeletion);
}
Thanks for your help.
Update: The annotation needs to be added to a library to enable it to be shared by different microservices.
We think that writing a new class-level annotation might help. It would run on class initialization, find all methods that are annotated with #PollableStreamListener, and schedule the polling to happen for each of the Kafka topics.
To slightly adjust the terminology and shift the focus, is it acceptable to bind the creation of such a construction to Spring's Application Context initialization? If so, you could create a Bean Factory Post Processor that would have been triggered for each #PollableStreamListener.
In a nutshell, BFPP runs before spring creates the beans during the application context initialization. This mechanism allows to "dynamically" create beans that in a runtime will be indistinguishable from those created by spring in a regular way, a kind of hook to the spring initialization lifecycle that you can use here.
So this BFPP and introspect the methods of your interest. Then based on the information found in the annotations / configuration This BFPP could register a Bean Definition per scheduled job of the bean (a class with all the required parameters that you could prepare as a part of the infrastructure). Then spring will read this bean definition and create the beans out of this bean definition as it usually does.
Here you can find an example of how to use this BFPP and more specifically its registerBeanDefintion method.
This question already has answers here:
What is difference between singleton and prototype bean?
(9 answers)
Closed 3 years ago.
When I using spring framework to write business code, I always use the singleton scope and avoid using the prototype scope. I think there is a performance difference between prototype and singleton. Because of the prototype scope, spring creates a new instance every call. And I think it is slower than using the singleton scope. Am I right? And am I giving too many considerations to the performance?
I can relate to the question, I have been researching it recently. Construction of objects is very cheap, unless they actually do some heavy lifting in the constructor. You never think twice about constructing a bunch of lambdas in one statement. That's not the problem.
The problem is Spring's inefficiency, the way it wasn't architectured right. I have recently benchmarked Spring vs Guice. Singletons are slightly faster with Spring, but Prototypes are 20 times slower.
From code sanity point of view, you should always prefer Prototypes. Guice defaults to prototypes. javax.inject.Inject documentation defaults to prototypes. Spring lists some vague historical reasons and does Singletons.
Prototypes are safer because they cannot accidentally store state and use it in the wrong context. They cannot store "userId" from one request and use it in another, since with Prototypes, a brand new instance with clean state gets created every time. That's how I learned this pattern: we cached the wrong user context accidentally when using Singletons with RequestScoped Providers. Ouch. That mistake is important to avoid. Getting CPU is a much smaller problem.
To summarize: use Prototypes for better code, and dont use Spring if performance is very important.
Yes, you are right prototype scoped beans consumes more resources. According to the documentation:
The non-singleton prototype scope of bean deployment results in the creation of a new bean instance every time a request for that specific bean is made.
The constructor is called at each request instead of only once for a singleton scoped bean. But there is another aspect to take into account. The documentation says:
Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called. The client code must clean up prototype-scoped objects and release expensive resources that the prototype beans hold. To get the Spring container to release resources held by prototype-scoped beans, try using a custom bean post-processor, which holds a reference to beans that need to be cleaned up.
In some respects, the Spring container’s role in regard to a prototype-scoped bean is a replacement for the Java new operator. All lifecycle management past that point must be handled by the client.
If you want to avoid an out of memory exception, you have to take care yourself of the release of all resources (such as database connections) hold by the prototype scoped beans.
Unless it's really needed, it's better to use singleton scoped beans.
I don't think you'll see any noticeable performance difference between prototypes and singletons in general in the most basic sense.
It's true that there is only one singleton bean instance in the application context, and instances of beans defined with "prototype" scope are created for every request to that bean, however, we're talking about the performance of new object creation and its very cheap these days and optimized for non-expensive objects.
However here are some caveats:
What if the Constructor of the bean calls some pretty expensive code, its not spring's fault of course, because the programmer wrote the code this way, but still, actually, some pretty expensive code will be called every time the bean is created and it can drain the performance.
Slightly more interesting: we usually don't place code like this in consturctor, instead we use "lifecyle" methods like #PostConstruct / #PreDestroy.
For Singletons spring will call the post-construct method once when it creates a singleton and after that will place the bean onto the application context.
When the application context gets closes (usually when the app shuts down) the pre-destroy method is called to free up the resources, etc.
However, with Prototype scoped beans it's not the case:
Spring creates them upon every request to the bean, then calls the post-construct method, again for every single instance of the bean it creates, then doesn't store the instance in the application context. This means that spring doesn't call at all pre-destroy methods (because it doesn't have a clue who are these objects, it doesn't really manage them after they're created).
So this can (again, not spring's fault) lead to serious performance differences between the two.
If we'll take it further, sometimes spring has to wrap the object into some sort of proxy. These proxies are usually done with java.lang.Proxy in case of interfaces or with Cglib which is based on inheritance. Now this fact alone, when we're talking about wrapping prototype-scoped beans into proxy, can become a source of the serious difference in performance because Proxies are generated in runtime and Wrapping an Object with proxy (especially with CGlib) is pretty expensive.
I'm writing an aspect for making that possible for dependencies from external libraries to return values that are correctly formatted for my application.
With this in mind, I've created an annotation with name #SafeReturns.
I wire this class from the external library with the help of spring and in addition, I add my annotation.
#SafeReturns
#Autowired
public PermissionsClient client;
Now I try to make an aspect of it, but unfortunately, I can't catch all the calls to all the methods on the field annotated with this annotation. I tried different pointcuts. e.g.
#Pointcut("execution(#myApp.SafeReturns * *(..))")
#Around("safeReturnsPointCut()")
public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {
}
None of them helps me to achieve the behaviour of catching all the methods. Is there a way to catch them?
There are several problems with your approach and your assumptions about aspect syntax and execution logic:
You are using Spring AOP, but that one only works with Spring-managed beans/components due to its proxy-based nature, as is well documented in the Spring AOP manual. It does not work with non-Spring third-party code.
In order to target third-party code you need to use full AspectJ via LTW (load-time weaving). The Spring AOP manual also explains how to configure LTW.
Your pointcut says to target all method executions (of Spring components, if you are using Spring AOP) where the methods are annotated by SafeReturns. Neither with Spring AOP nor with AspectJ can you expect this syntax to apply to objects that happen to be assigned to instance member variables with a certain annotation. So your expectations of how you dream AOP to work and how it really does are quite divergent.
My suggestion is to switch to AspectJ via LTW and then write pointcuts which either target external method execution()s directly or to solve the problem indirectly by routing your external calls through annotated facades and target them with your pointcuts. This would even work with Spring AOP if the facades are Spring components.
There also is a direct way of solving this with advanced AspectJ + some manual bookkeeping. You can use set() pointcuts in order to find out when objects are assigned to your annotated fields (or unassigned later). Then you can have the aspect do manual bookkeeping of assigned objects and make sure that whatever your aspect advices do is only triggered if the object in question happens to be assigned to an annotated member variable. This works, I also have done that in the past. But it means you have to weave all of your application's method calls and then dynamically decide via look-ups in your bookkeeping whether or not the code should be executed or not, because there yould be object instances which are not assigned to any of your annotated fields. This incurs a certain performance penalty because this kind of thing cannot be determined during compile time by any aspect weaver. Please see my answer here for sample code for the manual bookkeeping thing.
I hope that my explanation was not too complicated, but your issue is quite technical and intricate.
Maybe I'm not using the right terminology and that's why i can't find an answer, but I want to know how can I take information from a database to create beans that I can inject into the application?
Here's an example, rather than having this coded in a configuration file, I would like to possibly loop some values stored in a database and build these beans based on that:
#Bean
public CronTriggerFactoryBean cronTriggerFactoryBean() {
CronTriggerFactoryBean factory = new CronTriggerFactoryBean();
factory.setJobDetail(jobDetailFactoryBean().getObject());
factory.setStartDelay(3000);
factory.setCronExpression("0 0/2 * 1/1 * ? *");
return factory;
}
How can I build beans like this and have them become a part of the application?
There are probably multiple ways how to achieve that, but all of them are pretty complex with a lots of pitfalls. I would say that in your example you should not create triggers as separate beans but rather have a single service to manage your schedules (and leave it out of Spring).
The thing with Spring is, that it is not designed to act as a dynamic container (like OSGi for example). This means that for example #Autowired dependencies are initialized during context startup and stays the same till the application context is destroyed.
However it is possible to construct bean definitions on the fly during initialization. Best place would be BeanFactoryPostProcessor. But this would be called during context initialization. This means you will have no other beans available (like EntityManager, DataSource, ...).
Another possibility is to somehow take advantage of context hierarchy. You can create and destroy application contexts on-the-fly. However implementing that would require deeper knowledge of Spring's internals.
Question for others: not sure if it is possible to reference initialized beans from parent context during child context initialization.
After you load the necessary bean properties from Database , use BeanDefinitionBuilder. You can refer this link
I have a bunch of projects which declare some spring bean files. I would like to write a "library" which supplies a utility which takes some bean names and adds some behaviour "around" the objects (example: Call Counting, Monitoring, Logging etc)
One obvious way for doing this would be to add some AspectJ annotations in the spring xml files in the projects but I would like the "utility" to search for some beans and add behaviour to them (This way the projects themselves are not aware of the utility).
The utility will be declared in the spring xml file somewhere so it has access to the ApplicationContext as it could implement ApplicationContextAware interface however I am keen on exploring how one would go about modifying behaviour of another bean in the app context programmatically. ex, something like find a bean of id "OrderService", create an aspected bean with some monitoring/call counting etc around all methods and replace that bean in the application context for "OrderService"
I know there are disadvantages with this approach but what I am after is "IS it possible to do this? And if yes how?"
If you don't want to use AOP, you can achieve this using a BeanPostProcessor. The Spring documentation states:
The BeanPostProcessor interface defines callback methods that you can
implement to provide your own (or override the container's default)
instantiation logic, dependency-resolution logic, and so forth. If you
want to implement some custom logic after the Spring container
finishes instantiating, configuring, and otherwise initializing a
bean, you can plug in one or more BeanPostProcessor implementations.
So you may create and register a BeanPostProcessor and implement the postProcessAfterInitialization(Object bean, String beanName) method to modify the methods you want to customize. Here is an example.
(But I would still recommend that you do this with AOP as this is the classical use case for it and it's much easier and more declarative. With the bean() pointcut, you can even advise beans with names matching a certain pattern.)
You can create your own BeanPostProcessor. You just have two declare it in applicationContext.xml and it will be called for each bean during initialization of beans (in fact, just before or just after). In each call you get a the actual object and its name. There, you can, for example, wrap that object depending on its name or type.