Spring - How 'multiple' AOP behaviors to services are resolved? - java

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.

Related

Use class annotation to run on class initialization with Spring AOP

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.

Spring AOP Pointcut for methods invoked on field with annotation

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.

How does spring instantiate a bean from a annotated interface (e.g. JpaRepository)? [duplicate]

I have been working with Spring Data JPA repository in my project for some time and I know the below points:
In the repository interfaces, we can add the methods like findByCustomerNameAndPhone() (assuming customerName and phone are fields in the domain object).
Then, Spring provides the implementation by implementing the above repository interface methods at runtime (during the application run).
I am interested on how this has been coded and I have looked at the Spring JPA source code & APIs, but I could not find answers to the questions below:
How is the repository implementation class generated at runtime & methods being implemented and injected?
Does Spring Data JPA use CGlib or any bytecode manipulation libraries to implement the methods and inject dynamically?
Could you please help with the above queries and also provide any supported documentation ?
First of all, there's no code generation going on, which means: no CGLib, no byte-code generation at all. The fundamental approach is that a JDK proxy instance is created programmatically using Spring's ProxyFactory API to back the interface and a MethodInterceptor intercepts all calls to the instance and routes the method into the appropriate places:
If the repository has been initialized with a custom implementation part (see that part of the reference documentation for details), and the method invoked is implemented in that class, the call is routed there.
If the method is a query method (see DefaultRepositoryInformation for how that is determined), the store specific query execution mechanism kicks in and executes the query determined to be executed for that method at startup. For that a resolution mechanism is in place that tries to identify explicitly declared queries in various places (using #Query on the method, JPA named queries) eventually falling back to query derivation from the method name. For the query mechanism detection, see JpaQueryLookupStrategy. The parsing logic for the query derivation can be found in PartTree. The store specific translation into an actual query can be seen e.g. in JpaQueryCreator.
If none of the above apply the method executed has to be one implemented by a store-specific repository base class (SimpleJpaRepository in case of JPA) and the call is routed into an instance of that.
The method interceptor implementing that routing logic is QueryExecutorMethodInterceptor, the high level routing logic can be found here.
The creation of those proxies is encapsulated into a standard Java based Factory pattern implementation. The high-level proxy creation can be found in RepositoryFactorySupport. The store-specific implementations then add the necessary infrastructure components so that for JPA you can go ahead and just write code like this:
EntityManager em = … // obtain an EntityManager
JpaRepositoryFactory factory = new JpaRepositoryFactory(em);
UserRepository repository = factory.getRepository(UserRepository.class);
The reason I mention that explicitly is that it should become clear that, in its core, nothing of that code requires a Spring container to run in the first place. It needs Spring as a library on the classpath (because we prefer to not reinvent the wheel), but is container agnostic in general.
To ease the integration with DI containers we've of course then built integration with Spring Java configuration, an XML namespace, but also a CDI extension, so that Spring Data can be used in plain CDI scenarios.

How are Spring Data repositories actually implemented?

I have been working with Spring Data JPA repository in my project for some time and I know the below points:
In the repository interfaces, we can add the methods like findByCustomerNameAndPhone() (assuming customerName and phone are fields in the domain object).
Then, Spring provides the implementation by implementing the above repository interface methods at runtime (during the application run).
I am interested on how this has been coded and I have looked at the Spring JPA source code & APIs, but I could not find answers to the questions below:
How is the repository implementation class generated at runtime & methods being implemented and injected?
Does Spring Data JPA use CGlib or any bytecode manipulation libraries to implement the methods and inject dynamically?
Could you please help with the above queries and also provide any supported documentation ?
First of all, there's no code generation going on, which means: no CGLib, no byte-code generation at all. The fundamental approach is that a JDK proxy instance is created programmatically using Spring's ProxyFactory API to back the interface and a MethodInterceptor intercepts all calls to the instance and routes the method into the appropriate places:
If the repository has been initialized with a custom implementation part (see that part of the reference documentation for details), and the method invoked is implemented in that class, the call is routed there.
If the method is a query method (see DefaultRepositoryInformation for how that is determined), the store specific query execution mechanism kicks in and executes the query determined to be executed for that method at startup. For that a resolution mechanism is in place that tries to identify explicitly declared queries in various places (using #Query on the method, JPA named queries) eventually falling back to query derivation from the method name. For the query mechanism detection, see JpaQueryLookupStrategy. The parsing logic for the query derivation can be found in PartTree. The store specific translation into an actual query can be seen e.g. in JpaQueryCreator.
If none of the above apply the method executed has to be one implemented by a store-specific repository base class (SimpleJpaRepository in case of JPA) and the call is routed into an instance of that.
The method interceptor implementing that routing logic is QueryExecutorMethodInterceptor, the high level routing logic can be found here.
The creation of those proxies is encapsulated into a standard Java based Factory pattern implementation. The high-level proxy creation can be found in RepositoryFactorySupport. The store-specific implementations then add the necessary infrastructure components so that for JPA you can go ahead and just write code like this:
EntityManager em = … // obtain an EntityManager
JpaRepositoryFactory factory = new JpaRepositoryFactory(em);
UserRepository repository = factory.getRepository(UserRepository.class);
The reason I mention that explicitly is that it should become clear that, in its core, nothing of that code requires a Spring container to run in the first place. It needs Spring as a library on the classpath (because we prefer to not reinvent the wheel), but is container agnostic in general.
To ease the integration with DI containers we've of course then built integration with Spring Java configuration, an XML namespace, but also a CDI extension, so that Spring Data can be used in plain CDI scenarios.

Adding behaviour using Spring

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.

Categories