Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
482 views
in Technique[技术] by (71.8m points)

aspectj - Spring: register advice programmatically at runtime

Is it possible to register AOP advices programmatically, after the application has booted and the context has been initialized?

When I tried, the advices didn't work, supposedly because they need to wrap the bean BEFORE it gets available in the context.

Something like this (it doesn't work):

@Bean
private AspectJExpressionPointcutAdvisor createPointcutAdvisor(AWSXRayRecorder awsxRayRecorder, String name, String pointcut) {

    AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
    advisor.setExpression("execution ...()");
    advisor.setAdvice(new CustomAdvice("custom bean"));

    return advisor;
  }

Clarification: I need to read a list of advice from a config file, and register the pointcuts accordingly. I need the label for bookeeping purposes. The file contents are unknown at compile time.

label: execution(* com.my.ns.OtherClass(..))
label2: execution(* com.my.ns.Class(..)) 
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The previous solution is too invasive as it not only creates advice on the fly but also handles advising beans. This replicates functionality of Spring's AbstractAdvisorAutoProxyCreator, specifically the getAdvicesAndAdvisorsForBean method, where Spring will locate and apply eligible Advisors to each bean. A better approach is to simply programmatically create Advisors and let Spring handle the rest of the plumbing of advising beans, creating proxies, and so forth.

A simple way of creating a Advisor is to create a Advisor bean using the @Bean annotation:

@Bean
    public Advisor advisorBean() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(* com.testit.MyAspectedService.*(..))");
        return new DefaultPointcutAdvisor(pointcut, new MyMethodInterceptor());
    }

Where the class MyMethodInterceptor implements the MethodInterceptor interface:

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import java.lang.reflect.Method;

public class MyMethodInterceptor implements MethodInterceptor {


    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("in interceptor");

        //get the method and arguments we are intercepting
        Method method = invocation.getMethod();
        Object[] arguments = invocation.getArguments();
        //... do stuff before the method
        //call the underlying method
        return invocation.proceed();
    }

}

What this does is to create a around advice Advisor bean named "advisorBean" for all methods calls to a Spring bean MyAspectedService declared as

@Service
public class MyAspectedService {

    //various service methods
}

This approach focuses on only creating the necessary Advisors and interception implementation and delegates the weaving of the aspect to the Spring framework.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...