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

Rob*_*son 5 java aop annotations

有没有办法让这段代码有效?

LogonControl.java

@Audit(AuditType.LOGON)
public void login(String username, String password) {
 // do login
}
Run Code Online (Sandbox Code Playgroud)

AuditHandler.java

public void audit(AuditType auditType) {
 // persist audit
}
Run Code Online (Sandbox Code Playgroud)

最后一点是,每次调用login()时,都会调用audit(),并使用相应的audittype.

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

注意:我不想预定义将调用audit的方法,我是为可扩展框架编写的,其他人可能需要使用它.

dfa*_*dfa 16

使用反射很容易只使用@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");
    }

}
Run Code Online (Sandbox Code Playgroud)

@Audit定义为:

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

   Class<? extends Handler> handler();
}
Run Code Online (Sandbox Code Playgroud)

Handler在哪里:

interface Handler {

    void handle();
}

class LoginHandler implements Handler {

    public void handle() {
        System.out.println("HANDLER CALLED!");
    }
}
Run Code Online (Sandbox Code Playgroud)

现在真正的代码:

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()));
    }
}
Run Code Online (Sandbox Code Playgroud)

@测试:

    Login login = LoginFactory.createLogin();
    login.login("user", "secret");
    login.logout();
Run Code Online (Sandbox Code Playgroud)

输出:

HANDLER CALLED!
login
logout


duf*_*ymo 5

它已经完成 - 使用SpringGuice.

如果你想知道轮子是如何工作的,或者如果你认为你可以做一些明显更轻的东西,滚动你自己就有意义.在你开始之前确保两者都是真的.