Java:基于注释的代码注入的简单技术?

Java:基于注释的代码注入的简单技术?,java,annotations,aop,Java,Annotations,Aop,有没有办法让这段代码正常工作 LogonControl.java @Audit(AuditType.LOGON) public void login(String username, String password) { // do login } AuditHandler.java public void audit(AuditType auditType) { // persist audit } 结束语是,每次调用login()时,也会调用audit(),并使用适当的auditty

有没有办法让这段代码正常工作

LogonControl.java

@Audit(AuditType.LOGON)
public void login(String username, String password) {
 // do login
}
AuditHandler.java

public void audit(AuditType auditType) {
 // persist audit
}
结束语是,每次调用login()时,也会调用audit(),并使用适当的audittype

我想AOP可能是解决这个问题的方法,但我希望它尽可能简单(我看过的AspectJ教程通常有非常复杂的注释)

注意:我不想预先定义调用audit的方法,我写这篇文章是为了一个可扩展的框架,其他人可能需要使用它。

已经完成-使用或


如果你想的话,或者如果你认为你可以做一些明显更轻的事情,那么你自己滚动是有意义的。在开始之前,请确保这两种方法都是正确的。

使用反射很简单,只需使用@Audit注释一个方法,就像JUnit中的测试运行程序一样:

public interface Login {

    void login(String name, String password);
 }

public class LoginImpl implements Login {

    @Audit(handler = LoginHandler.class)
    public void login(String name, String password) {
        System.out.println("login");
    }

}
@审计的定义如下:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Audit {

   Class<? extends Handler> handler();
}
现在是真正的代码:

public class LoginFactory {

    private static class AuditInvocationHandler implements InvocationHandler {

        private final Login realLogin;

        public AuditInvocationHandler(Login realLogin) {
            this.realLogin = realLogin;
        }

        public Object invoke(Object proxy, Method method, Object[] args) 
                      throws Throwable {
            Method realMethod = realLogin.getClass().getMethod(
                                        method.getName(), 
                                        method.getParameterTypes());
            Audit audit = realMethod.getAnnotation(Audit.class);

            if (audit != null) {
                audit.handler().newInstance().handle();
            }

            return method.invoke(realLogin, args);
        }
    }

    public static Login createLogin() {
        return (Login) Proxy.newProxyInstance(
                LoginFactory.class.getClassLoader(),
                new Class[]{Login.class},
                new AuditInvocationHandler(new LoginImpl()));
    }
}
@测试:

    Login login = LoginFactory.createLogin();
    login.login("user", "secret");
    login.logout();
输出:

HANDLER CALLED! login logout HANDLER打电话来了! 登录 注销
查看Guice中的拦截方法:


类似的方法应该适用于任何AOP框架。

代码应该做什么?每次调用带有@audit注释的方法时,是否都应该调用audit()方法?@Esko Luontola-是的,没错。相信我-我不想自己使用,但Spring是供我使用的。我将研究Guice,一开始它看起来不错。我的观点是,您不必吞下整个Spring来从中获益。与AspectJ相比,SpringAOP的重量相当轻(功能也不太强大)。它也许能很好地满足你的需要。您不必处理所有Spring,只需处理与AOP相关的一小部分。我发现Spring在这些情况下工作得很好。为了一个狭隘的目的,可以将其引入传统应用程序,而不需要完全重写。试试看,春天已经有了内置的跟踪功能。只需一点配置,无需新代码,您就可以做任何事情。@duffymo,您可以发布一个指向跟踪方面的链接吗?请查看org.springframework.aop.interceptor包中的拦截器:。我想到的是SimpleTraceInterceptor或PerformanceMonitorInterceptor。谢谢。这句话让我有点害怕:“不可能在非Guice构造的实例上使用方法拦截。”据我所知,这意味着我必须先使用Guice.getInstance(LogonController.class)才能进行方法拦截?我将研究这在另一个AOP框架中是否可行。这意味着Guice必须构造对象,但这并不意味着您必须要求Guice构造它。该对象可以被注入到由Guice构造的另一个对象中。从本质上讲,Guice将在dfa提供的解决方案中取代工厂。这似乎是最好的解决方案。我希望我的代码能够保持原样,只添加注释,但经过大量研究,我认为这是不可能的。干杯 HANDLER CALLED! login logout