Java 如何在建议之前增加Spring方法中使用的参数

Java 如何在建议之前增加Spring方法中使用的参数,java,spring,spring-boot,aop,aspectj,Java,Spring,Spring Boot,Aop,Aspectj,我从我的Java语言老师那里得到一项任务,在建议之前使用SpringAOP增加RESTfulWeb服务中的计数器(id)。我不知道怎么做。我们使用spring.io中的默认restful应用程序。这是我修改过的代码: 应用程序: package sut.ist012m.Ruygo.hello_goodbye; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfig

我从我的Java语言老师那里得到一项任务,在建议之前使用SpringAOP增加RESTfulWeb服务中的计数器(id)。我不知道怎么做。我们使用spring.io中的默认restful应用程序。这是我修改过的代码:

应用程序:

package sut.ist012m.Ruygo.hello_goodbye;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy(proxyTargetClass=true)

public class Application {

    public static void main(String[] args) {

        final ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
        final Controller Controller = run.getBean(Controller.class);
    }
}
控制器:

package sut.ist012m.Ruygo.hello_goodbye;

import java.util.concurrent.atomic.AtomicLong;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Controller {

    private static final String hellotemplate = "Hello, %s!";
    private static final String adrtemplate = "Welcome to %s";
    public AtomicLong counter1 = new AtomicLong();

    @RequestMapping("/greeting")
    public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name,
                             @RequestParam(value="city", defaultValue="Moscow") String city) {
        return new Greeting(counter1.incrementAndGet(),
                String.format(hellotemplate, name),
                    String.format(adrtemplate, city));
    }

}
问候:

package sut.ist012m.Ruygo.hello_goodbye;

public class Greeting {
    private final long id;
    private final String content;
    private final String adrcontent;

    public Greeting( long id,
                     String content,
                     String adrcontent) {
        this.id = id;
        this.content = content;
        this.adrcontent = adrcontent;
    }

    public long getId() {

        return id;
    }

    public String getContent() {

        return content;
    }

    public String getAdrcontent() {

        return adrcontent;
    }

反方面(我写的):

在正常情况下,然后你们刷新网页你们会看到id=1,id=2,id=3。。。 我们希望看到id=1,11,21,23等等。 我不明白在“建议前公开无效”中该写些什么。
Spring不控制“Greeting”类可以吗?

不能使用before-advice修改参数/参数,必须使用around-advice修改参数

@Around(value="execution(* sut.ist012m.Ruygo.hello_goodbye.Greeting.*(..)) ")
public void aroundAdvice(ProceedingJoinPoint pjp){
   Object[] args = pjp.getArgs();
   // you can modify it by modifying args
   args[0] = .....; // modify your first parameter (id)
   args[1] = .....; // modify your second parameter (content)
   args[2] = .....; // modify your third parameter (adrcontent)
   // call proceed method from pjp and pass args as its parameter
   pjp.proceed(args);
}

SpringAOP将只建议SpringBeans。因此,您所关心的“Spring不控制“Meeting”类可以吗?”(我猜您在这里指的是问候语)是正确的。这是不好的,因为你试图建议一个问候豆

还要注意的是,使用SpringAOP不能向构造函数提供建议

如果您的拦截需要包括方法调用甚至构造函数 在目标类中,考虑使用弹簧驱动的本机。 AspectJ编织代替了Spring基于代理的AOP框架

为了更好地理解以下代码,您必须通读以下参考资料

使用SpringAOP实现您的需求有多种方法,我只是遵循您的建议

修改了GreetingController并自动连接了一个具有作用域请求的问候bean

@RestController
public class GreetingController {
    private static final String hellotemplate = "Hello, %s!";
    private static final String adrtemplate = "Welcome to %s";

    @Autowired
    Greeting greeting;

    @RequestMapping("/greeting")
    public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name,
            @RequestParam(value = "city", defaultValue = "Moscow") String city) throws Exception {
        greeting.setAdrcontent(String.format(adrtemplate, city));
        greeting.setContent(String.format(hellotemplate, name));
        Greeting g = getTarget(greeting);
        return g;
    }

    // Get the actual target object to avoid exception when returning
    // Comment out this method to observe what happens.
    private Greeting getTarget(Greeting greeting) throws Exception {
        while (AopUtils.isAopProxy(greeting) && greeting instanceof Advised) {
            Object target = ((Advised) greeting).getTargetSource().getTarget();
            greeting = (Greeting) target;
        } 
        return greeting;
    }
}
将问候语类修改为Springbean

@Component
@RequestScope
public class Greeting {
    private long id;
    private String content;
    private String adrcontent;
    
    // Getters and setters
}
反方面

@Aspect
@Component
public class CounterAspect {

    public AtomicLong counter1 = new AtomicLong(1);

    @Before(value = "execution(* sut.ist012m.Ruygo.hello_goodbye.Greeting.*(..)) && target(greeting)")
    public void beforeAdvice(Greeting greeting) {
        if (greeting.getId() == 0) {
            greeting.setId(counter1.getAndAdd(10));
            System.out.println(greeting.getId());
        }
    }

}
此通知针对问候语bean上的任何公共方法调用执行,并通过
问候语
参数使实际的问候语对象可用于通知。(请参阅:)


作为工作的一部分,您可以尝试不同的方法来优化此代码。

非常感谢!这真是个好建议!很高兴这有帮助。如果您的问题得到了回答,请将此标记为答案(勾选标记),如果它对您有帮助,也请向上投票。(向上箭头)
@Aspect
@Component
public class CounterAspect {

    public AtomicLong counter1 = new AtomicLong(1);

    @Before(value = "execution(* sut.ist012m.Ruygo.hello_goodbye.Greeting.*(..)) && target(greeting)")
    public void beforeAdvice(Greeting greeting) {
        if (greeting.getId() == 0) {
            greeting.setId(counter1.getAndAdd(10));
            System.out.println(greeting.getId());
        }
    }

}