Spring aop intercepting calls from within the same service class - java

I have a same scenario as mentioned in
Spring #Transaction method call by the method within the same class, does not work?
I was referring to answer #1 which i thought would work for my simple pojo class but it didnt. In my case i dont have annotation #Transaction. Its a simple pojo class. I wish to intercept each method adduser as well as addusers using spring aop if i take example in post above.
Is it possible to intercept method that is being called from the same service call? I was referring to AspectJAwareProxy which does the trick but doesnt resolve the issue as a whole. What i mean is i dont want anything to be added to my business logic. So i want to avoid any coding except for defining pointcut and defining the advice. Is it something possible using Java and spring aop? I am using CGlib to generate proxy. Spring version is 3.0.5.Release.
Thanks,
Ajay

For this to work, you have to use load-time weaving instead of proxying. The reason is because spring uses proxying to achieve AOP functionality (such as transaction support). Once inside a class instance, any method-calls to methods in the same instance will be directly against the actual instance object, not the wrapping proxy so AOP advices will not be considered. Load-time weaving works differently. There, you have an outside java agent that manipulates the classes on a byte-code level to inject the AOP support.
You will need to
1: Modify your java command-line used to include the spring aspectj agent
2: add
<context:load-time-weaver aspectj-weaving="on" />
<tx:annotation-driven mode="aspectj" />
to your spring cofig.
Read more:
AspectJ Load Time Weaving with Spring Transaction Manager and Maven
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-aj-ltw

Related

AOP without Spring

I implemented Logger using Spring 4.0 and AspectJ. But I'm now trying to make the logger independent of Spring. I couldn't initialize aspect in my application. Any hint to start will be helpful.
Thanks in advance.
If you have a Spring- based app and you want to use AspectJ, it is better to use the AspectJ features offered by Spring. You can also use Spring AOP without AspectJ.
You can make cross-cutting functionality by using AspectJ annotations with Spring AOP.
#Aspect annotation allow you to make the aspect from your Logger class.
In the Logger class define set of the pointcut by using the #Pointcut annotation. By using annotations #Before, #AfterReturning, #AfterThrowing define the advices and when they will be applied relative to the set of the pointcut (before, after, in the case of throwing an exception).
Then include the aop namespace in Spring configuration file and register the object of the class AnnotationAwareAspectJAutoProxyCreator by using <aop:aspectj-autoproxy> configuration element.
This component also performs proxying of classes which have #Aspect annotation and which have methods included in a certain set of the pointcut.
How to use AspectJ without Spring you can find here, for example:
Using AspectJ logging without Spring

Compile/load time weaving with spring

The docs explain that, the LTW has to enabled either through the use of <context:load-time-weaver/> xml instruction or the use of #EnableLoadTimeWeaving annotation. However, I have done neither, but I still see that aspects are woven correctly in my projects!
In this case, I don't think they are woven at compile-time (but are they?), so it's surely got to be load-time-weaving?
Even if that's the case, how does it automatically choose to weave aspects in during load-time? Shouldn't the aspects remain unwoven if they are not turned on using one of the ways mentioned above as the docs say?
I've got the aspectj-weaver in my classpath, but that can't be enough to choose either of these weaving types anyway, can it?
Spring AOP does not rely on AspectJ byte code weaving. It just borrows the annotations used to define aspects from the AspectJ project. It is a separately implemented framework that uses run-time proxies to implement aspects. If you have <aop:aspectj-autoproxy /> in your application context then spring is using proxies to implement supported aspects defined on beans that are in the container.
Proxies can only achieve a sub-set of the full capabilities of the actual AspectJ system, basically advice that wraps methods. Due to their nature proxies have following limitations:
interception on external calls only (while breaching proxy boundary)
interception on public members only (private/protected can't be intercepted)
unawareness to local calls (or calls with this or super)
If you want to be able to advise fields for example, you would need to enable the use of Native AspectJ.

Spring ApplicationContext.getBean(Class c) not working for proxy classes

I need to look up beans via their class type. When the beans have been wrapped by a Proxy (some methods are #Transactional) - the ApplicatoinContext fails to find them. I find that if I look them up via an interface, it works but in this case I'm working with a concrete class type. I know the bean is of the type I'm looking for but the getBean() method fails.
I can debug (and fix) the problem in Spring's AbstractBeanFactory code. The issue is that it checks the type of the beanInstance against type I'm requesting but the beanInstance.getClass() is a Proxy. AbstractBeanFactory should compensate for this and compare the type to the proxy's target class.
I have a fix for this but I don't particularly want to use a patched version of Spring and I suspect there must be something I can configure to get this working, or is this really a bug?
There are two major ways Spring implements AOP (e.g. #Transactional support): either by using proxy interfaces or CGLIB.
With interfaces (default) if your class implements any interfaces, Spring will create a proxy implementing all that interfaces. From now on you can only work with your bean through that interfaces. Your class is deeply burried inside them.
If you enable proxying target classes instead via cglib:
<aop:config proxy-target-class="true">
Spring will create a subclass (obvoiusly still implementing all your interfaces) instead. This will fix your problem. However remember that the returned object is not really your class but dynamically generated subclass that wraps and delegates to your original object. This shouldn't be a problem in most of the cases.
And no, of course this is not a bug but well known behaviour and no, there is no need to patch Spring.
See also
Location of the proxy class generated by Spring AOP
Getting Spring Error "Bean named 'x' must be of type [y], but was actually of type [$Proxy]" in Jenkins
How to mix CGLIB and JDK proxies in Spring configuration files?
Mocking a property of a CGLIB proxied service not working
<context:component-scan base-package="<Your base package name goes here>" />
<aop:aspectj-autoproxy />
<aop:config proxy-target-class="true"/>
write these three lines in applicationContext.xml this worked for me.

spring and aspectj, intercept method of a non-proxy object

i want to intercept method from a non-proxied object.
I have a class instance MyClass myClassInstance=new MyClass() and i want to intercept call of myClassInstance methods.
I know all works good with proxies, but i need aspect on non proxied.
Is this possible?
Thanks.
It is possible, but it is not desirable.
You can use #Configurable and AspectJ will intercept calls. Read the 7.8.1 Using AspectJ to dependency inject domain objects with Spring section of the docs about it.
In short - AspectJ plugs some "magic" either compile-time or load-time (with a respective weaver), which modifies the classes so that they become part of the spring context.
As of why I think it is undesirable - this is dark magic that happens by modifying the classes' structure. It's not an object-oriented approach, and I think it will be hard to support. Imagine 6 months later a colleague of yours is debugging a nasty issue. It could take days before he realizes this magic is happening. This opinion is subjection though. The functionality is there and if you need it - use it.
Using Spring, I do not believe so (I appear to be wrong), using AspectJ I believe you can as long as you compile all the code with the AspectJ compiler. However I have never tried it.
You can enable load time weaving in Spring. Then the class loader will weave whatever aspects you define into your classes when they are loaded - regardless of whether they are being created by Spring.
You'll need to enable LTW by adding this line to your context file:
See:
http://static.springsource.org/spring/docs/3.0.0.M4/spring-framework-reference/html/ch07s08.html#aop-aj-ltw

Is fine grained control of aspectj-autoproxy possible in spring?

If I just add <aop:aspectj-autoproxy proxy-target-class="false"/> to the start of my spring context, every single bean that implements an interface gets a JDK proxy. I would really like to limit the proxying A) to classes that actually need proxies or B) classes that I specify as needing proxies.
I tried using the aop:scoped-proxy stanza within an xml bean defintion for the beans that need proxies, but it turns out this does not seem to give me aop-advice.
I also tried adding <aop:aspectj-autoproxy ....> near the end of my spring xml file, but before adding all the beans that need proxies, but it does not seem to work properly.
I have a lot of beans with interfaces but only a (well defined) handful need AoP advice, and those proxies are messing up my stacktraces big time. (I have peeked at spring 3.0 and suspect it's going to be possible there but it seems like it's a while away).
Is this possible in 2.5.X ?
As can be seen in AbstractAdvisorAutoProxyCreator.java line 67 (Spring 2.5.6), the autoproxy creator really only does what I ask it to. It does not autoproxy more than it thinks necessary.
It turns out it's the kind of pointcut expression you use greatly influences how much proxying this class does; the annotation I was using was
#Around(value="#target(myannotation)")
This basically means spring generates a proxy that decides to intercept based on the type of the actual invocation target. The downside of this is that spring tries to do this with all available beans in the applicationcontext. If I'd been using something like#within instead, spring would be using the interface to decide if autoproxying should take place, and this can statically be determined at the time the applicationcontext is built.
So now I only have two classes that are proxied ;)

Categories

Resources