Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • we use Compile-time weaving - it's the most powerful possibility from all aspect-weaving possibilities (e.g. load-time weaving (LTW) doesn't allow to create aspects around private and final methods). Another advantage is that it doesn't have negative performance impact on running application (LTW makes weaving during class initialization). Disadvantage can be that compilation has to be by AspectJ compiler => build script and IDE must be adjust.

    There is blog post about performance comparision: The results are a bit surprising for me for two reasons. First, creating objects marked as @Configurable is less than 4 times slower than creating ordinary objects using new operator.

    Info
    • Compile-time weaving is the simplest approach. When you have the source code for an application, ajc will compile from source and produce woven class files as output. The invocation of the weaver is integral to the ajc compilation process. The aspects themselves may be in source or binary form. If the aspects are required for the affected classes to compile, then you must weave at compile-time. Aspects are required, e.g., when they add members to a class and other classes being compiled reference the added members.

    • Post-compile weaving (also sometimes called binary weaving) is used to weave existing class files and JAR files. As with compile-time weaving, the aspects used for weaving may be in source or binary form, and may themselves be woven by aspects.

    • 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. To support this, one or more "weaving class loaders", either provided explicitly by the run-time environment or enabled through a "weaving agent" are required.


  • we use JDK dynamic proxies (Dynamic Proxies vs. CGLib proxies)
  • Spring AOP and AspectJ runs in parallel - instances created from Spring factory will be controled by Spring. If classes are created outside of Spring IoC container (classes marked with annotation @Configurable) then AspectJ is used
  • pointcuts syntax = AspectJ syntax

    Info

    Using aspectj-autoproxy means that @Aspect annotations are recognized, but Spring proxies are still being created, see this quote from the documentation: Do not be misled by the name of the element: using it will result in the creation of Spring AOP proxies. The @AspectJ style of aspect declaration is just being used here, but the AspectJ runtime is not involved.


  • all production code (not test code) is compiled by aspectj with use aspectj-maven-plugin, standard compilation with maven-compiler-plugin is disabled (again for production code only)

    Code Block
    <!-- configure Java compilers -->
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven-compiler-plugin.version}</version>
        <configuration>
            <!-- http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#configuration-metadata-annotation-processor -->
            <proc>none</proc>
            <source>${java.version}</source>
            <target>${java.version}</target>
            <encoding>UTF-8</encoding>
            <showDeprecation>true</showDeprecation>
            <showWarnings>true</showWarnings>
        </configuration>
        <!-- compiler is disabled because of aspectj compiler -->
        <executions>
            <execution>
                <id>default-compile</id>
                <phase>none</phase>
            </execution>
        </executions>
    </plugin>
    
    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <version>1.10</version>
        <executions>
            <execution>
                <goals>
                    <goal>compile</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <!-- https://eclipse.org/aspectj/doc/next/devguide/ajc-ref.html -->
            <complianceLevel>${java.version}</complianceLevel>
            <source>${java.version}</source>
            <target>${java.version}</target>
            <Xlint>ignore</Xlint>
            <!--<showWeaveInfo>true</showWeaveInfo>-->
            <!--<forceAjcCompile>true</forceAjcCompile>-->
            <weaveDirectories>
                <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
            </weaveDirectories>
            <aspectLibraries>
                <aspectLibrary>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-aspects</artifactId>
                </aspectLibrary>
            </aspectLibraries>
        </configuration>
        <dependencies>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjtools</artifactId>
                <version>${aspectj.version}</version>
            </dependency>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>${aspectj.version}</version>
            </dependency>
        </dependencies>
    </plugin>


  • dependency on AspectJ libraries and Spring aspects is necessary (configuration from root pom.xml). We can also add dependency on own custom aspects.

    Code Block
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
               <artifactId>spring-aspects</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
        </dependency>
    </dependencies>


  • Spring Boot configuration spring.aop.auto=true in application.properties is equal to the annotation @EnableAspectJAutoProxy
  • when we want to non-managed classes into Spring IoC container then annotation @EnableSpringConfigured is needed

Creating own aspect

There is module wiseporter-logging (not from OpenHub framework) that contains aspect com.openwise.wiseporter.log.EntitySavingAspect - this aspect logs entity before saving:

...