Apply Order of Spring Aspects with Same Order - spring

Suppose multiple aspects are in application and be applied on a certain method. The annotation #order or Ordered interface can specify their precedence.
But if the values of #Order are same, how to determine the apply order?

When two pieces of advice defined in different aspects both need to run at the same join point, unless you specify otherwise the order of execution is undefined. You can control the order of execution by specifying precedence. This is done in the normal Spring way by either implementing the org.springframework.core.Ordered interface in the aspect class or annotating it with the Order annotation. Given two aspects, the aspect returning the lower value from Ordered.getValue() (or the annotation value) has the higher precedence.
It cannot be controlled, reference from doc 6.2.4.7

Related

What Default order of beans creating in Spring Boot?

What Default order of beans creating in Spring Boot if we don't use #DependsOn and #Order?
I searched for documentation and found only "How to control the order of creating"
From this Spring doc (scroll down a bit):
...Your target beans can implement the
org.springframework.core.Ordered interface or use the #Order or
standard #Priority annotation if you want items in the array or list
to be sorted in a specific order. Otherwise, their order follows the
registration order of the corresponding target bean definitions in the
container.
You can declare the #Order annotation at the target class level and on
#Bean methods, potentially for individual bean definitions (in case of
multiple definitions that use the same bean class). #Order values may
influence priorities at injection points, but be aware that they do
not influence singleton startup order, which is an orthogonal concern
determined by dependency relationships and #DependsOn declarations.

spring annotation advice order on method level

I have created 2 custom spring #annotations. I need to define the order of these annotations, on method-level, not on class-level. Does #order, work on the method level, too?
#Aspect
#Component
public class ABC {
private ThreadLocal<logDTO> myThreadLocal;
#Before("#annotation(CommunicationLogInit)")
public void CampaignLogsInit(){
myThreadLocal = new ThreadLocal<logDTO>();
myThreadLocal.set(new logDTO());
}
#Around("#annotation(CommunicationAudit)")
public Object generateLog(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
Method method = signature.getMethod();
int counter = 0;
for(Parameter parameter : method.getParameters()){
Annotation eventName = parameter.getAnnotation(EventName.class);
Annotation rtnInfo = parameter.getAnnotation(RtnInfo.class);
if(eventName!=null){
System.out.println(joinPoint.getArgs()[counter]);
myThreadLocal.get().setName("ABC");
}
}
}
}
The Spring AOP manual answers your question in section advice ordering:
Advice Ordering
What happens when multiple pieces of advice all want to run at the same join point? Spring AOP follows the same precedence rules as AspectJ to determine the order of advice execution. The highest precedence advice runs first “on the way in” (so, given two pieces of before advice, the one with highest precedence runs first). “On the way out” from a join point, the highest precedence advice runs last (so, given two pieces of after advice, the one with the highest precedence will run second).
When two pieces of advice defined in different aspects both need to run at the same join point, unless you specify otherwise, the order of execution is undefined. You can control the order of execution by specifying precedence. This is done in the normal Spring way by either implementing the org.springframework.core.Ordered interface in the aspect class or annotating it with the Order annotation. Given two aspects, the aspect returning the lower value from Ordered.getValue() (or the annotation value) has the higher precedence.
When two pieces of advice defined in the same aspect both need to run at the same join point, the ordering is undefined (since there is no way to retrieve the declaration order through reflection for javac-compiled classes). Consider collapsing such advice methods into one advice method per join point in each aspect class or refactor the pieces of advice into separate aspect classes that you can order at the aspect level.
I think the last paragraph is of particular interest to you.

Way to influence the order returned by ApplicationContext.getBeanDefinitionNames()?

I am trying to invoke an operation of a set of beans by retrieving them from appContext.getBeanDefinitionNames().The order of invoking the operation matters to me as one bean's operation is dependent on other.
I have tried the following to set this order.
1.PriorityOrdered interface
2.#DependsOn annotation
3.BeansPostProcessor interface
But none of them seem to influence the order in the list. By default it is returning the beans in the order in which they are encountered in classpath.
Two questions.
1.What does it mean when the above approaches set the order of initialization to the bean?
2.Can the order of retrieval of bean names using appContext.getBeanDefinitionNames() be influenced in any way?
I didn't understand from your question what is really your problem. Do you want to alter the order of initializing beans or to get the names of beans in the order they have been defined in your configurations?
1.What does it mean when the above approaches set the order of initialization to the bean?
ApplicationContext is responsible for instantiating, configuring and wiring your application's beans. ApplicationContext in an early step of it's life cycle reads your configurations (XML, Annotations, Java code configurations, etc) and instantiates those beans. When we are talking about the order of initializing beans, we mean which bean will be instantiated by the ApplicationContext sooner and which will be instantiated later. For example if you have two classes A and B in which B depends on A like below:
class A {
}
class B {
private A a;
public B(A a) {
this.a = a;
}
}
As you can see in order to instantiate B we need an instance of A.
DependsOn
Beans on which the current bean depends. Any beans specified are guaranteed to be created by the container before this bean. (DependsOn Documentation)
BeanPostProcessor
A BeanPostProcessor allows you to modify a been after it is instantiated by the container. I don't think you can achieve what you want with a bean post processor. Docs
PriorityOrdered
PriorityOrdered is an extension of Ordered interface. From the documentation:
Ordered is an interface that can be implemented by objects that should
be orderable, for example in a Collection. The actual order can be
interpreted as prioritization, with the first object (with the lowest
order value) having the highest priority.
Note that there is also a priority marker for this interface:
PriorityOrdered. Order values expressed by PriorityOrdered objects
always apply before same order values expressed by plain Ordered
objects.
From the documentation of PriorityOrdered
Extension of the Ordered interface, expressing a priority ordering:
order values expressed by PriorityOrdered objects always apply before
same order values expressed by plain Ordered objects. This is
primarily a special-purpose interface, used for objects where it is
particularly important to recognize prioritized objects first, without
even obtaining the remaining objects. A typical example: prioritized
post-processors in a Spring ApplicationContext.
Also I don't think you can achieve what you want from this interface too.
2.Can the order of retrieval of bean names using appContext.getBeanDefinitionNames() be influenced in any way?
The getBeanDefinitionNames() method only returns an array of strings containing the names of all the beans defined in the current factory (Docs).

Before vs Around advice precedence in #AspectJ-Style annotations

I have converted a simple Spring project made with pure aop namespace xml coding to the same project but using annotations this time.
I've noticed that now the before-part of the around advice comes out before the before advice, which is the exact opposite behavior of the project's result when I was using aop namespace xml coding.
Is it the default behavior of the annotation style?
See Advice ordering:
When two pieces of advice defined in different aspects both need to run at the same join point, unless you specify otherwise the order of execution is undefined. You can control the order of execution by specifying precedence. This is done in the normal Spring way by either implementing the org.springframework.core.Ordered interface in the aspect class or annotating it with the Order annotation. Given two aspects, the aspect returning the lower value from Ordered.getValue() (or the annotation value) has the higher precedence.
Since the ordering is undefined, it could possibly vary even between multiple executions (having the same xml config).

spring annotation advice order

I have a method with two annotations
#One
#Two
public Object foo() { ... }
I have two aspects that use these annotations
#Around("#annotation(One)")
public Object doOne(final ProceedingJoinPoint joinPoint) throws Throwable { ... }
and
#Around("#annotation(Two)")
public Object doTwo(final ProceedingJoinPoint joinPoint) throws Throwable { ... }
But is the order in which these advices are executed indeterminate?
The order is undefined. If you need determinate order, use #Order annotation.
See also:
7.2.4.7 Advice ordering
6.2.4.7. Advice ordering
What happens when multiple pieces of advice all want to run at the
same join point? Spring AOP follows the same precedence rules as
AspectJ to determine the order of advice execution. The highest
precedence advice runs first "on the way in" (so given two pieces of
before advice, the one with highest precedence runs first). "On the
way out" from a join point, the highest precedence advice runs last
(so given two pieces of after advice, the one with the highest
precedence will run second).
When two pieces of advice defined in different aspects both need to
run at the same join point, unless you specify otherwise the order of
execution is undefined. You can control the order of execution by
specifying precedence. This is done in the normal Spring way by either
implementing the org.springframework.core.Ordered interface in the
aspect class or annotating it with the Order annotation. Given two
aspects, the aspect returning the lower value from Ordered.getValue()
(or the annotation value) has the higher precedence.
When two pieces of advice defined in the same aspect both need to run
at the same join point, the ordering is undefined (since there is no
way to retrieve the declaration order via reflection for
javac-compiled classes). Consider collapsing such advice methods into
one advice method per joinpoint in each aspect class, or refactor the
pieces of advice into separate aspect classes - which can be ordered
at the aspect level.
http://static.springsource.org/spring/docs/2.0.x/reference/aop.html
Order is undefined unless explicitly indicated (for instance, by using #Order)
On the way in to a joinpoint, the advice with lowest Order value
gets executed first.
On the way out from the joinpoint, the advice
with highest Order value gets executed first.
When two pieces of advice defined in the same aspect both need to run at the same join point, the ordering is undefined.Consider collapsing such advice methods into one advice method per join point in each aspect class, or refactor the pieces of advice into separate aspect classes - which can be ordered at the aspect level.
this is how to do:
When two pieces of advice defined in the same aspect both need to run at the same join point, the ordering is undefined (since there is no way to retrieve the declaration order via reflection for javac-compiled classes). Consider collapsing such advice methods into one advice method per join point in each aspect class, or refactor the pieces of advice into separate aspect classes - which can be ordered at the aspect level.
https://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-ataspectj-advice-ordering

Resources