Is it possible to call an advise in Spring AOP whenever a member variable instance is referenced. If not, is there any way this can be achieved, via Spring AOP or else?
Update:
I'd like to achieve this without accessor methods
Spring AOP only applies to method invocations.
Spring AOP currently supports only method execution join points
(advising the execution of methods on Spring beans).
You won't be able to advise field accesses. You'll need AspectJ for that.
Related
Spring created a bean if I change a local variable of that class. forex - I change a variable value.
will that new value be available for any new thread or call to spring application api.
Spring beans are created for the purpose of dependency injection. That means, you don't pass these bean objects as parameters nor do you change these beans as they are singleton in nature. These beans are injected in corresponding classes where their properties and methods could be used.
And, if you are changing these beans in some method, then the entire fundamental of making beans for the purpose of dependency injection will be breached.
Hope this clarifies your doubt.
Also, if it is not what you asked, can you please share some codeblock where the things could be more clear?
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.
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.
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.
I want to know that whether we can apply 'multiple' AOP behaviors to our service classes or not?
Lets just say, i do this to my BankServiceImpl class:
#Transactional on top of one of the method, accountTransfer(), and
and some custom <aop> pointcut on the execution of another method someOtherMethod().
Then will Spring be able to generate one proxy where accountTransfer() is made transactional and someOtherMethod() is also given aop behaviour?
Does any one has an idea on how Spring resolves multiple AOP behaviors?
It looks like Spring creates a single proxy object with all of the advice types in it. This proxy object will implement the org.springframework.aop.framework.Advised regardless of if it's a JDK dynamic proxy or a CGLIB proxy.
If you have multiple advisors, the order of their execution is undefined unless you make it explict by implementing the Ordered interface or the #Ordered annotation. You can find more on ordering here. Springs transactional aspects default to lowest priority.