I have no time just now to provide a "recipe", but you have several options:
- if() pointcut combined with config file or startup parameter specifying a boolean checked by the pointcut. Advantage: dynamic, can be switched on for production debugging on demand. Disadvantage: aspect code is part of your deliverables in production.
- Adjust build job so code is not woven for production builds, only for development builds. Advantage: no overhead in production. Disadvantages: (small) one-time effort to adjust the build plan(s). Not dynamic.
- Load-time weaving (LTW): Do not weave your non-production aspects into the production code at all, but only use it on demand via LTW (JVM start-up parameter). Advantages: no code pollution, similar to option 2. Still flexible if you need LTW on demand. Disadvantages: some overhead during application start-up for LTW. You need to be able to influence the start parameters of the target platform.
Now it is your choice. After having chosen, the "recipe" comes next. There is no "one size fits all", you have options.
Alexander Kriegisch
Good morning,
I've dig into the mailing list without
really finding what I'm looking for.
I want a design pattern, clear, easy
to understand by newbies and implement to enable or disable (weaving) an
aspect during compile time. I saw that using @Aspect style is something
different from the solution with no annotation (native style). As
the product go to the production, I want to disable some aspect without
removing the source code.
As I do not to reinvent the wheel, I
suppose that you already have the answer, a good one, not too far
to the mouse'click ;)
Thank you.
Here is the aspect, we just calculate
the elapsed time for particular calls and we log the result. Later we extract
from log the result and we compute and draw graphics from the collected
data.
@Aspect
@DeclarePrecedence("*,MonitorServiceBehavior")
public
class
MonitorServiceBehavior extends
LoggingBaseBehavior {
@Pointcut("call(*
com.nested.common.soa.client.services.interfaces.IClientService.*(..))
&& !within(com.nested.common.soa.client.services.impl.*)")
public
void
elapsedSoaTimeMonitor() {};
@Pointcut("execution(public
* com.nested.crm.domain.services.impl.*.*(..))")
public
void
elapsedServiceTimeMonitor() {};
@Pointcut("call(public
* com.nested.canada..service..*.*(..))")
public
void
externalServiceTimeMonitor() {};
@Pointcut("call(public
* com.nested.canada..services..*.*(..))")
public
void
commonApiServiceTimeMonitor() {};
@Around(value
= "(elapsedSoaTimeMonitor()
|| elapsedServiceTimeMonitor() || externalServiceTimeMonitor() || commonApiServiceTimeMonitor())
&& this(log)")
public
Object elapsedTimeMonitor(ProceedingJoinPoint pjp, JoinPoint.StaticPart
jps, Loggable log) throws
Throwable {
long
startTime = System.nanoTime();
Object
result = pjp.proceed();
long
elapsedTime = System.nanoTime() - startTime;
log.getLog().info(jps.getSignature().getName()
+ " - elapsed
time: " + elapsedTime + "
- " + ((double)elapsedTime/1000000));
return
result;
}
}
@Aspect
public
abstract
class
LoggingBaseBehavior {
protected
String buildParameters(Object[] parameters) {
if
(parameters == null)
{
return
null;
}
StringBuilder sb = new
StringBuilder();
for
(int
i = 0; i< parameters.length;
i++) {
sb.append("Param")
.append(i+1)
.append(" : ")
.append("'")
.append(parameters[i])
.append("'");
if
(i+1 < parameters.length)
{ sb.append("
- "); }
}
return
sb.toString();
}
/*
* The interface and the implementation of Loggable
class.
*/
public
interface
Loggable {
Logger getLog();
};
public
static
class
ServantLogger implements
Loggable {
private
transient
Logger log
= null;
public
ServantLogger(Class<? extends
Object> clazz) {
this.log
= LoggerFactory.getLogger(clazz);
}
@Override
public
Logger getLog() {
return
log;
}
}
}
Jean ANDRÉ
|