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 ;)
Related
As far as I know whenever I use interfaces for my beans, JDK Dynamic Proxies should be used instead of CGLIB. To be on teh safe side, I make sure I don't even have CGLIB in the classpath of my Spring Boot app.
However, when my controller implements an interface I see this in the stacktrace(never mind the stacktrace rootcause, it was a validation error):
at com.yuranos.documented.api.controllers.BookingControllerImpl.convertToDto(BookingControllerImpl.java:57)
at com.yuranos.documented.api.controllers.BookingControllerImpl.getBookingById(BookingControllerImpl.java:29)
at com.yuranos.documented.api.controllers.BookingControllerImpl$$FastClassBySpringCGLIB$$890fcd8a.invoke(<generated>)
What is even more confusing is that when I remove the interface, this strangely named proxy disappears:
at com.yuranos.documented.api.controllers.BookingControllerImpl.convertToDto(BookingControllerImpl.java:60)
at com.yuranos.documented.api.controllers.BookingControllerImpl.getBookingById(BookingControllerImpl.java:32)
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.
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.
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
I've been struggling with this for a few hours now.
I'm trying to migrate my Spring XML configuration to a full Java based configuration.
I'm using AnnotationConfigApplicationContext as a context implementation.
I'm having trouble finding an Java equivalent for this line, from my old XML configuration:
<tx:annotation-driven transaction-manager="transactionManager" />
As a result, Spring doesn't manage the transactions.
In my Java configuration I have initialized the relevant beans for transactions: the session factory, the transactional manager, etc, but without that line, no transaction proxy is used, so no transactions are actually in place.
So my question is how do I either translate that line to my Java context configuration or how to I go about solving the problem in another way.
Any help is appreciated.
Thanks.
You can now use #EnableTransactionManagement.
See: http://blog.springsource.com/2011/06/10/spring-3-1-m2-configuration-enhancements/
In my experience, it's not practical to entirely replace the XML config with #Bean-style config. Some things do make more sense configured in java, specifically your own bean definitions. But when it comes to infrastructural-type declarations like <tx:annotation-driven>, the XML syntax is a lot more concise.
You can reproduce the same effect in pure java, but it ends up being cumbersome and unintuitive, since things like <tx:annotation-driven> are typically interactions of complex low-level Spring infrastructure classes that you really don't want to touch.
My advice - mix and match, using each of Java and XML for their own strengths. This is quite easy to do. I prefer to keep the normal XML ApplicationContext classes, and then declare my #Configuration classes as beans in that XML context, alongside things like <tx:annotation-driven>.
Take a look at https://spring.io/blog/2011/02/17/spring-3-1-m1-introducing-featurespecification-support. Spring 3.1's FeatureSpecification classes such as TxAnnotationDriven are designed to solve exactly the problem described above.