在运行时动态添加新的 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 或某处

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

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/679.html

大家都在问