Reputation: 8067
I am new to Spring AOP and trying to create a demo using aop:around
.
A simple bean class:
public class Employee {
private String name;
public String getName() {
System.out.println("Name: " + name);
return name;
}
public void setName(String name) {
this.name = name;
}
}
Aspect implementation:
public class PrintingAspect {
public void performPrinting(ProceedingJoinPoint point){
try {
System.out.println("Before Printing!!!");
point.proceed();
System.out.println("After Printing!!!");
} catch (Throwable e) {
System.out.println("Exception Printing");
}
}
}
Context XML:
<bean id="aspect" class="com.aop.aspect.PrintingAspect">
</bean>
<bean id="employee" class="com.aop.model.Employee">
<property name="name" value="XXX"></property>
</bean>
<aop:config>
<aop:pointcut id="empName" expression="execution(* com.aop.model.Employee.getName(..))"/>
<aop:aspect ref="aspect">
<aop:around pointcut-ref="empName" method="performPrinting"/>
</aop:aspect>
</aop:config>
App.java
public class App
{
public static void main( String[] args )
{
ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
Employee empl = (Employee)context.getBean("employee");
System.out.println("Employee Names: " + empl.getName());
}
}
The o/p I am getting is:
Before Printing!!! Name: XXX After Printing!!! Employee Names: null
Why is the last one null ?
Upvotes: 0
Views: 7629
Reputation: 1373
@user182944, although you may have solved this long ago, I'm answering it because it may help others hitting the same issue!
Because your Aspect returns void (i.e. nothing), then any method you apply it to will return null.
With your current code, when you execute getName(), the Aspect kicks in and executes getName() but then throws away the result since your Aspect returns void, leaving your calling code with a null to deal with.
To ensure that the method you annotate returns the value you expect it to, you need your Aspect to return the object that's returned by it - i.e. by the .proceed()
call.
In this case we know your method returns a String, so we could define the Aspect as returning a String. However, since we don't necessarily always know in advance what kind of object will be returned by the annotated method, the simplest solution is to declare your annotation with the return type Object
.
So, to fix this, simply make your Aspect return the object returned by the annotated method, similar to @Rahul Jain's incomplete snippet), like this:
public class PrintingAspect {
public Object performPrinting(ProceedingJoinPoint point){
Object returnValue = null;
try {
System.out.println("Before Printing!!!");
returnValue = point.proceed();
System.out.println("After Printing!!!");
} catch (Throwable e) {
System.out.println("Exception Printing");
}
return returnValue;
}
}
Now that we have an Aspect that returns the annotated method's response, we can execute our getName() method and our Aspect will kick in and then return the String that getName() returned, as you expected.
Hope this helps explain what's going on!
Upvotes: 0
Reputation: 115
Point.proceed() in the below code is responsible for actual exceution of the code and as your are using around advice you should capture the return value and return in the below method. As you are return nothing in the below method Its coming as null.
Please let me know if it doesn't work.I haven't tested It But It will Work.
public void performPrinting(ProceedingJoinPoint point){
try {
System.out.println("Before Printing!!!");
Object returnValue = point.proceed();
System.out.println("After Printing!!!");
} catch (Throwable e) {
System.out.println("Exception Printing");
}
return returnValue;
}
Upvotes: 1
Reputation: 279920
One way to do it is with these changes:
XML:
<aop:pointcut id="empName"
expression="execution(* com.example.Employee.getName(..))" />
Java:
public void performPrinting(ProceedingJoinPoint jp) { // Here empl is coming null
System.out.println("Before Printing!!!");
System.out.println(((Employee)jp.getTarget()).getName()); // empl is coming as NULL
System.out.println("After Printing!!!");
}
In other words, you get access to the target
which is the object that is being proxied for the AOP advice to be applied.
Upvotes: 1