Date: Thu, 28 Mar 2024 19:57:03 +0000 (UTC) Message-ID: <533395382.31.1711655823454@9129a348be68> Subject: Exported From Confluence MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_Part_30_1432818791.1711655823454" ------=_Part_30_1432818791.1711655823454 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Content-Location: file:///C:/exported.html
we use Compile-time we= aving - it's the most powerful possibility from a= ll aspect-weaving possibilities (e.g. load-time weaving (LTW) doesn't allow to create a= spects 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 =3D> build script and= IDE must be adjust.
There is blog post about performan= ce comparision: The results are a bit surprising for me for two re= asons. First, creating objects marked as @Configurable is less than 4 times= slower than creating ordinary objects using new operator.
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 integr= al 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 com= pile, 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 weav= ing) is used to weave existing class files and JAR files. As with compile-t= ime 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 defere= d until the point that a class loader loads a class file and defines the cl= ass to the JVM. To support this, one or more "weaving class loaders", eithe= r provided explicitly by the run-time environment or enabled through a "wea= ving agent" are required.
pointcuts syntax =3D AspectJ syntax
Using aspectj-autoproxy means that @Aspect annotations are recognize= d, but Spring proxies are still being created, see this quote from the docu= mentation: 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 involve= d.
all production code (not test code) is compiled by aspectj with use = ;aspectj-maven-plugin, standard compilation with maven-co= mpiler-plugin is disabled (again for production code only)
<!--= 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/ht= mlsingle/#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</we= aveDirectory> </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 (configu= ration from root pom.xml). We can also add dependency on own custo= m aspects.
<dep= endencies> <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>
There is module wiseporter-logging (not from Op= enHub framework) that contains aspect com.openwise.wiseport= er.log.EntitySavingAspect - this aspect logs entity before saving:
/** * Aspect example. * * @author <a href=3D"mailto:petr.juza@openwise.cz">Petr Juza</a&g= t; * @since 0.1 */ @Aspect @Configurable public class EntitySavingAspect { @Autowired private ApplicationContext ctx; public EntitySavingAspect() { System.out.println("EntitySavingAspect created ..."); } @Before("com.openwise.wiseporter.commons.aop.CommonPointcuts.preSavingE= ntity()") public void logBeforeSaving(JoinPoint jp) { System.out.println("AOP (" + (ctx !=3D null) + "): " + jp.getSignat= ure()); } }
where is reference to CommonPointcuts class (module<= em> wiseporter-commons):
@Aspect public class CommonPointcuts { /** * Join point is pre-saving method in entities. */ @Pointcut(value =3D "execution(void com.openwise.wiseporter.coreapi.ent= ity.Saveable+.preSave())") public void preSavingEntity() {} /** * Join point is post-saving method in entities. */ @Pointcut(value =3D "execution(void com.openwise.wiseporter.coreapi.ent= ity.Saveable+.postSave())") public void postSavingEntity() {} /** * Join point is deleting method in entities. */ @Pointcut(value =3D "execution(void com.openwise.wiseporter.coreapi.ent= ity.Deletable+.delete())") public void inDeletingEntity() {} }
It's necessary to adjust AspectJ compilation to use this aspect in anoth= er modules. We need to add dependency to this module with aspect - see addi= ng wiseporter-logging module into aspectLibraries&nb= sp;below.
<bui= ld> <plugins> <!-- added dependency to wiseporter-logging --> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <configuration> <aspectLibraries> <aspectLibrary> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </aspectLibrary> <aspectLibrary> <groupId>${project.groupId}</groupId> <artifactId>wiseporter-logging</artifactId= > </aspectLibrary> </aspectLibraries> </configuration> </plugin> </plugins> </build>
If aspect itself should be Spring bean (e.g. I need to use auto-wiring t= o another beans) then aspect has to be marked by annotation @Configurab= le.
Tips for troubleshooting:
Spring AOP - log levels configuration
logging= .level.org.springframework.aop=3DTRACE logging.level.org.aspectj=3DTRACE
See Getting started to know how set up IDE for AspectJ c= ompilation.