微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在运行时动态添加新的 AOP 顾问,表达式来自 Spring Framework 中的其余端点

如何解决在运行时动态添加新的 AOP 顾问,表达式来自 Spring Framework 中的其余端点

我正在尝试实现向 Spring bean 添加新顾问的功能。想法是我将编写 Rest 端点,并将获得 pointcut 表达式 和我想通过该端点应用表达式的 Bean 名称。获得切入点表达式和 bean 名称后,我将使用表达式创建新的顾问程序。然后我将这个顾问添加到现有 bean 的代理中。(bean 名称来自休息点。)

根据这个问题https://stackoverflow.com/a/49080647,我在下面编写了用于添加新顾问的代码。在 setAdvisor(Class beanClazz,Advisor advisor) 方法中,Advised advisedBean = ((Advised) bean); Casting 行不起作用。可能是因为 bean 实例来自 ApplicationContext 不是代理,所以我得到了 CastingException。

然后我尝试实现来创建我自己的 bean 代理,并再次将 Advisor 添加到此代理中,但它不起作用。这次我可以向代理添加顾问,但 MethodInterceptor 没有调用,所以 aop 不起作用。可能是它不起作用的原因,我没有把新创建的代理放到 ApplicationContext 等地方。那么我应该把这个代理放在哪里,或者我如何改变 Spring 来使用这个代理而不是 ApplicationContext 中 bean 的真实实例。>

除了这个解决方案,如果你有另一个解决方案,我会很高兴。

您可以在下面检查类的实现。

LoggingAttacher.Java

import org.aopalliance.aop.Advice;
import org.apache.naming.factory.beanfactory;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionpointcut;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

    @Component
    public class LoggingAttacher implements ApplicationContextAware {
    
        private static ApplicationContext context;
        
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            context = applicationContext;
        }
        
        static <T> T getBean(Class<T> beanClazz) {
            return context.getBean(beanClazz);
        }
        
        public static <T> void setAdvisor(Class<T> beanClazz,Advisor advisor) {
            try {
                T bean = getBean(beanClazz);
                Advised advisedBean = ((Advised) bean);
                advisedBean.addAdvisor(advisor);
            } catch (BeansException e) {
                e.printstacktrace();
            }
        }
    
        public static <T> void setAdvisorWithNewProxy(Class<T> beanClazz,Advisor advisor) {
            try {
                T bean = getBean(beanClazz);
                Advised advisedBean = ((Advised) createProxy(bean));
                advisedBean.addAdvisor(advisor);
            } catch (BeansException e) {
                e.printstacktrace();
            }
        }
    
        public static <T> Advised createProxy(T bean) {
            if (bean instanceof Advised) {
                System.out.println("Bean " + bean + " is already an advised proxy,doing nothing");
                return (Advised) bean;
            }
            System.out.println("Creating proxy for bean " + bean);
            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.setTarget(bean);
            return (Advised) proxyFactory.getProxy();
        }
    
        // Note:  MypointcutAdvisor extends DefaultpointcutAdvisor!!!
        public static MypointcutAdvisor createAdvisor(String expression) {
            AspectJExpressionpointcut pointcut = new AspectJExpressionpointcut();
            pointcut.setExpression(expression);
            return new MypointcutAdvisor(pointcut,new LoggingInterceptor());

启用AopController.java

@RestController
public class EnablingAopController {



    @GetMapping("/enable-aop")
    public String enableAop() {
        MypointcutAdvisor mypointcutAdvisor = LoggingAttacher.createAdvisor("execution(* com.argmnt.logging.logging_project.AppService.*(..))");
        LoggingAttacher.setAdvisor(AppService.class,mypointcutAdvisor);
        return "example1";
    }
}

MypointcutAdvisor.java

import org.aopalliance.aop.Advice;
import org.springframework.aop.pointcut;
import org.springframework.aop.support.DefaultpointcutAdvisor;

public class MypointcutAdvisor extends DefaultpointcutAdvisor {

    public MypointcutAdvisor(pointcut pointcut,Advice advice) {
        super(pointcut,advice);
    }
}

LoggingInterceptor.java

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

public class LoggingInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("in interceptor");
        return invocation.proceed();
    }

注意:如果你问我还在 ApplicationMain 类上添加了 @EnableAspectJAutoproxy 注释。

我还检查了 https://docs.spring.io/spring-framework/docs/3.0.0.M4/reference/html/ch08s02.html 并找到了一些关于 8.2.4.2 Dynamic pointcuts 的内容,但它是很小的一段,我不太明白。

还找到了 https://stackoverflow.com/a/43052250 这个用于删除添加 bean 到 ApplicationContext 的答案,但找不到如何将我创建的代理放入 ApplicationContext 或某处

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。