I am using load-time weaving for a spring (2.5.x) project but I don't know what it is the purpose of it in general. I tried little googling but didn't find the upcoming pages useful. The only thing I understood is that it is something about AOP.
I noticed that it is used for older spring versions also wondering why is that?
Weaving is an AOP concept and it is the phase of integrating the aspects with the targeted code. After weaving, aspects are applied to the original code.
This process can take place in different times like compile and load. This article explains the different weaving times and LTW of AspectJ.
It says about LTW:
Load-time weaving (LTW) is simply binary weaving defered until the point that a class loader loads a class file and defines the class to the JVM.
Related
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.
Because Spring-driven AspectJ LTW is unable to weave classes loaded before Spring initializes, I'm converting a Spring project to pure Aspectj LTW (with the AspectJ weaver java agent).
However, this collaterally enables AOP in our Unit Tests because I need to add AspectJ's agent to the Maven Surefire plugin argLine parameter and to the default TestNG configuration in my team's IDE (IntelliJ IDEA).
This wouldn't be a problem if our Aspects were not dependent on Spring, but some of them actually require Spring beans to be injected in their fields via #Resource notation. As Spring is not started during Unit Tests, that fields will be null and result in NullPointerExceptions.
Even though I could configure two independent executions of the Surefire plugin during the build process: one with the agent and the other without it; this solution would become impractical as each developer would still need to change the IDE's test configuration for unit tests vs other tests that actually require AOP and start Spring, for every independent test execution (i.e. outside of Maven build process).
What would be the best approach in order to solve this problem? Is there any way to disable AspectJ's LTW while still keeping the java agent configuration intact? Or maybe another and more flexible way to configure AspectJ's LTW that doesn't have the problems of Spring-driven AspectJ LTW?
We could argue about whether or not it is a good design decision to make pure AspectJ aspects dependent on Spring magic or if it would be an option to inject mock-ups for your Spring beans into the aspects. Actually a unit test is not a unit test if it requires such a framework. The same is arguably true for aspects.
Anyway, here is a cheap solution: Use if() pointcuts for all relevant advice and make them dependent on whether you are in testing mode or not. The performance overhead will usually be minimal, don't worry. Just give it a try before you say it is too expensive.
Also possible, but more expensive would be to determine if a test class is in the control flow of the currently intercepted joinpoint via cflow() or cflowbelow(). I do not recommend it in this case though.
A third option might be to add another META-INF/aop.xml to the classpath in testing mode which contains a global exclude statement excluding all classes from weaving. The AspectJ documentation explains how multiple aop.xml are merged logically. Probably this option is the best because it does not require you to change your aspects. I have not tried, but I would if you encounter any difficulties and give me a sign.
I asked this question a few days ago, and managed to get it working using compile-time weaving.
However, when the application runs and it invokes the toString() method which I mixed into my DTO via AOP, I get the exception below.
I didn't expect AspectJ to be required in the runtime classpath. After all, I've used compile-time weaving, so the bytecode should already be in its final state, right? Why is AspectJ expected to be present at runtime?
java.lang.ClassNotFoundException: org.aspectj.lang.NoAspectBoundException
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:506)[osgi-3.6.2.R36x_v20110210.jar:]
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422)[osgi-3.6.2.R36x_v20110210.jar:]
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:410)[osgi-3.6.2.R36x_v20110210.jar:]
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)[osgi-3.6.2.R36x_v20110210.jar:]
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)[:1.6.0_35]
... 51 more
Is there a way to instruct AspectJ to drop all references to itself in the resulting bytecode?
N.B.: I'm running in an OSGi environment - but that's definitely irrelevant.
Whether you use compile-time, post-compile-time or load-time weaving, the woven bytecode will have a dependency on a small number of types - shipping them in a jar is seen as easier than generating them into every compiled app. These types are encapsulated in the small jar 'aspectjrt.jar'. You won't need the weaver jar or the compiler jar on the classpath, just the small runtime jar. It contains a few different things:
definitions of the runtime visible annotations that might have been used to write the aspect (#Before, #Aspect)
exception types for when things go wrong (NoAspectBoundException) or to implement language features (SoftException)
utility code to implement some language features, for example cflow threadlocal stack management.
all the support classes for thisJoinPoint. When you access something like getSignature() on thisJoinPoint you might get back a MemberSignature.
If would be possible to avoid a lot of these if you aren't using those language features, but NoAspectBoundException would likely still be an issue - even the simplest aspect will depend on that. Right now there is no way to compile that will avoid the jar dependency entirely.
It would be possible to modify AspectJ to do extra code generation to avoid the dependency entirely, but that isn't a common request and so no work has been done on it.
(There are builds of aspectjrt.jar that include the right OSGi manifest info, for use in that environment - the jar included in the standard distro doesn't get that manifest correct right now)
I believe you'll still need the AspectJ runtime libraries regardless of when the weaving took place.
I came cross a article about AOP, there it is mentioned that Aspect weaving can happen during the compile time, class loading time and during runtime.
In java, I could imagine, rather understand, how aspect weaving would actually happens during compile time. Proxy class are generated during class compilation itself(with aspect enabled on project). Generated bytecode would have proxy code.
But I am still wondering what exactly (actually) happen, during class loading time weaving and runtime weaving. Does the proxy class gets generated while loading the class? Does aspect library add any programmatic instruction in .class (while compiling) file for proxy class generation?
Spring AOP actually uses Java Dynamic Proxies for interfaces and, if necessary, cglib for non-interface types. It only works for Spring Beans. Proxies are generated automatically for all methods matched by a so-called pointcut. This is done during wiring.
AspectJ however does not need or even use proxies, it directly generates byte code which is woven into the existing byte code. AspectJ is much more powerful and can do more than just method interception.
For compile-time weaving (CTW) this is done by the AspectJ compiler ajc. Instead of native AspectJ syntax (which is a superset of Java) you can also use a Java annotation style way of defining aspects, often called the #AspectJ syntax. In this case you can compile the aspects with javac and use the aspect weaver in a separate build step. The result is basically the same. In both cases, during runtime you need a small AspectJ runtime library in order for the aspects to work as expected.
The difference between CTW and LTW (load-time weaving) is that the weaving step is deferred until classloading time. In order to make this work you need a Java agent library, called the AspectJ weaver, on the JVM command line. Java agents are started before normal application classes are loaded and can thus influence classloading and instrument the loaded byte code as desired. This approach is also used by profiling tools or similar.
So obviously LTW does not work with source code but class files, i.e. AspectJ can weave its aspect code into any regular Java class file. This can also be done before runtime, i.e. you can weave aspect code into an external library for which you do not have the source code, creating a new, modified version of it in order to save the time for LTW every time the library is loaded. This often is called binary weaving. With some extra knowledge it is even possible to weave aspect code into the JDK, i.e. by creating a modified rt.jar including aspect code. But this is nothing you normally do, I just wanted to mention that it is possible.
Not necessarily at compile time. In Java, through reflection and classloader, you can see and even or modify create methods and classes at runtime, programmatically.
For example,
"hello".getClass().getMethod("substring", Integer.TYPE).invoke("my sharona", 3)
Will return "sharona", extracting the method substring from a String instance and applying it to another object.
Using a custom classloader, you can define how your class is loaded from the system. This way you can define a method which will called to load (or generate!) the bytecode for a class. You can also use the system classloader to load the bytecode of a class and inspect it.
This technique is widely used by Mozilla Rhino, which can use it to load a compiled JavaScript as a Java bytecode for greater efficiency, or JavAssist, which allows you to create classes, methods, fields and anything at runtime.
Also application servers like JBoss or TomCat use reflection to inspect and manipulate the code, especially through annotations.
Not sure what run-time weaving is. In load-time weaving the agent intercepts the class loading and modifies the byte-code before passing it on to the class loader.
To see how this works is quite easy, for example using AspectJ. You could use compile time weaving and disassemble the code to see exactly how it works. AspectJ can also be instructed to save on disk the generated classes during load time weaving.
i am applying AspectJ in spring source tool
do i need to configure load time or compile weaving in spring source tool
i will be very happy if any provide details of using AspectJ for applying Aspect on Spring Source Tool
This is a very advanced topic, way beyond the scope of a single StackOverflow question.
Basically:
The simplest case is Spring AOP,
where you don't use AspectJ at all,
but create Java proxies from AspectJ
annotations. This is also the least
powerful option. Only a few pointcuts
are supported, and the targets must
be Spring Beans.
The most powerful option is static
AspectJ compilation, which you
usually integrate in your build
system (works fine with ant or
maven). Your class files are actually
changed to include the aspects. This
is called compile-time weaving.
Load-time weaving is somewhere
inbetween. You want to advise code,
but you don't want to change the
class files, so you "advise the
classloader" (this is not an adequate
definition, but it gives you an
idea). Loadtime-weaving is also
usually your only choice if you want
to add aspects to 3rd party library
code.
You should read AspectJ in Action by Ramnivas Laddad to understand all the subtle differences.
Either way, the settings you use in STS should reflect the settings you have in your build system. The section 7. Aspect Oriented Programming with Spring from the Spring Reference is also very helpful.