注释仅适用于接口的方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了注释仅适用于接口的方法相关的知识,希望对你有一定的参考价值。
我有一个注释:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Loggable { }
和方面:
@Aspect
public class AspectLogger {
@Around("@annotation(aspects.Loggable)")
public void aroundLogging(ProceedingJoinPoint joinPoint) {
System.out.println("aroundLogging()");
throw new AuthentificationFailException();
}
}
我也有接口和类:
public interface IAuthInteractor {
public User authorization(String login, String password);
}
public class AuthInteractor implements IAuthInteractor {
private EntityDAO<User> userDAO;
private ITokenGenerator tokenGenerator;
public AuthInteractor(EntityDAO<User> userDAO,
ITokenGenerator tokenGenerator) {
this.userDAO = userDAO;
this.tokenGenerator = tokenGenerator;
}
@Loggable
public User authorization1(String login, String password) {
return null;
}
@Loggable
public User authorization(String login, String password) {
return null;
}
}
对于第一种方法(authorization1),注释不起作用。对于方法授权(在interafce中描述),注释有效。
为什么这样工作?如何在没有界面的情况下工作?
答案
首先,方面的建议有一个void
返回类型,即它将永远不会为返回其他类型的方法启动,例如User
。方面甚至不应该编译。在任何情况下它都不适合我。 AspectJ编译器说:
applying to join point that doesn't return void: method-execution(de.scrum_master.app.User de.scrum_master.app.AuthInteractor.authorization(java.lang.String, java.lang.String))
所以,假设你改变了你的建议
@Around("@annotation(aspects.Loggable)")
public Object aroundLogging(ProceedingJoinPoint joinPoint) {
System.out.println("aroundLogging()");
throw new AuthentificationFailException();
}
它将编译并启动。我在本地测试它。
现在让我快速更改建议以实际进入原始方法,而不是总是抛出异常,这样我们可以测试更多,而不会一直捕获异常。我还想打印实际的连接点签名,这样我们就可以看到发生了什么:
@Around("@annotation(aspects.Loggable)")
public Object aroundLogging(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println(joinPoint);
//throw new AuthentificationFailException();
return joinPoint.proceed();
}
如果那时你将这个main
方法添加到你的接口实现类:
public static void main(String[] args) {
System.out.println("Interface object");
IAuthInteractor iAuthInteractor = new AuthInteractor(null, null);
iAuthInteractor.authorization("user", "pw");
System.out.println("
Implementation object");
AuthInteractor authInteractor = new AuthInteractor(null, null);
authInteractor.authorization("user", "pw");
authInteractor.authorization1("user", "pw");
}
控制台日志应该打印这样的东西,假设您使用AspectJ而不仅仅是通过Spring AOP的“AOP lite”,它不支持call()
连接点:
Interface object
execution(User de.scrum_master.app.AuthInteractor.authorization(String, String))
Implementation object
call(User de.scrum_master.app.AuthInteractor.authorization(String, String))
execution(User de.scrum_master.app.AuthInteractor.authorization(String, String))
call(User de.scrum_master.app.AuthInteractor.authorization1(String, String))
execution(User de.scrum_master.app.AuthInteractor.authorization1(String, String))
如您所见,执行总是被捕获,但是调用不适用于接口类型实例,因为接口方法没有注释,只有实现。
顺便说一句,方法注释无论如何都不会被继承,因此使用@Inherited
对注释类型的@Target({ElementType.METHOD})
元注释有点无用。
以上是关于注释仅适用于接口的方法的主要内容,如果未能解决你的问题,请参考以下文章
@TargetApi 注释是不是仅适用于一个 Api 级别或更高级别?
userLocation 上的中心 MKMapView(最初) - 仅适用于 iPhone 4?