I am creating a java library for logging purpose so that if any application uses my library then spring AOP's advices are applied to each method of the application. But in my library, I don't know the base package of the applications that will be using it. So, the applications should specify their base package in the application.properties file and my library will use it and put it in my pointcut as a variable. But seems like pointcut expressions only accepts contants inside it.
I don't want to go for annotation based approach.
@Component
@Aspect
@Slf4j
public class LoggingAop {
@Value("${base.package}")
String basePackage;
@Pointcut("within("+basePackage+"..*)") //error
public void logAllMethods()
{
}
}
Answers for the following questions explains why this is not possible with annotation based Spring AOP configuration
Spring boot supports xml based configurations and the requirement can be achieved as follows.
Assuming we have to intercept all the method calls within base package com.app.service
Have an entry in resources/application.properties.
base.package=com.app.service
An Aspect to log method calls within the base package can be as follows
package com.app.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogAspect {
Logger log = LoggerFactory.getLogger(LogAspect.class);
public Object logAllMethods(ProceedingJoinPoint pjp) throws Throwable {
log.info("Log before method call");
try {
return pjp.proceed();
}finally {
log.info("Log after method call");
}
}
}
The aop configuration can be defined as follows .
File : resources/aop-application-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="logAspect" class="com.app.aspect.LogAspect"></bean>
<aop:config>
<aop:aspect id="logallaspect" ref="logAspect" >
<!-- @Around -->
<aop:pointcut id="logAllMethodsAround" expression="within(${base.package}..*)" />
<aop:around method="logAllMethods" pointcut-ref="logAllMethodsAround" />
</aop:aspect>
</aop:config>
</beans>
Do note that the pointcut expression is constructed with the application.properties entry.
Remember to load the aop-application-context.xml as follows
@SpringBootApplication
@ImportResource("classpath:aop-application-context.xml")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The above code will advice all the interceptable Spring bean method calls within the defined base package and logs them .
Hope this helps.