构建或者运行阶段提供一些元数据,不影响正常运行逻辑,简化开发
Java提供了一些内置注解,并且实现了相关功能
Java提供了一些注解来构建自定义注解
首先我们定义两个比较常见作用域的自定义注解,在开发过程中我们一般都是定义运行时的注解,编译时的注解一般都是实现APT,用于一些编译时候的校验和生成字节码,代表的有Lombok框架。
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Hello {
String value() default "";
}
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Chinese {
}
现在我们有了自定义注解但是他没有实现任何功能,就只起装饰作用,下面我们来模拟一个场景,一个Person类有order行为,我们希望通过注解在点单前加上打招呼,Person有一个属性name,我们希望校验这个人名字由汉字组成
public class Person implements Action {
@Chinese
private String name;
@Override
@Hello("服务员")
public void order() {
System.out.println("可以给我一个汉堡包么?");
}
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Person() {
}
}
public class Proxys implements InvocationHandler {
private Object target;
public Proxys(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if (this.target instanceof Person) {
Person person = (Person) this.target;
// 判断Person类,name字段有没有加Chinese注解
if (person.getClass()
.getDeclaredField("name")
.isAnnotationPresent(Chinese.class)) {
// 判断名字是不是汉字
if (Objects.nonNull(person.getName()) &&
!person.getName().matches("[\\u4E00-\\u9FA5]+")) {
throw new IllegalArgumentException("Person Name is not chinese");
}
}
Method targetMethod = person.getClass().getMethod(methodName);
if ("order".equals(methodName)) {
// 拦截接口实现类中order方法判断是否有Hello注解
if (targetMethod.isAnnotationPresent(Hello.class)) {
System.out.println("你好," +
targetMethod.getAnnotation(Hello.class).value());
} else if (method.isAnnotationPresent(Hello.class)) { // 拦截接口中order方法判断是否有Hello注解
System.out.println("你好," +
method.getAnnotation(Hello.class).value());
}
return method.invoke(this.target, args);
}
}
return null;
}
public static Object getProxy(Object action) {
Proxys handler = new Proxys(action);
return Proxy.newProxyInstance(
action.getClass().getClassLoader(),
action.getClass().getInterfaces(),
handler);
}
}
可以看到我们的注解起到效果了
public class Test {
public static void main(String[] args) {
Action person1 = (Action) Proxys.getProxy(new Person("匿名"));
person1.order();
Action person2 = (Action) Proxys.getProxy(new Person("Sun"));
person2.order();
}
/**
* 输出:
* 你好,服务员
* 可以给我一个汉堡包么?
* Exception in thread "main" java.lang.IllegalArgumentException: Person Name is not chinese
* at reflect.annotations.Proxys.invoke(Proxys.java:32)
* at com.sun.proxy.$Proxy0.order(Unknown Source)
* at reflect.annotations.Test.main(Test.java:9)
*/
}
目前Spring框架用的比较多,我们定义和上面一样的hello注解
@Aspect
@Component
public class HelloAspect {
@Pointcut("@ (com.github.freshchen.springbootcore.annotation.Hello)")
private void pointcut(){}
@Before("pointcut() && @annotation(hello)")
public void hello(Hello hello){
System.out.println("你好," + hello.value());
}
}
同样起到了效果,Spring真香
@SpringBootApplication
public class SpringbootCoreApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(SpringbootCoreApplication.class, args);
Person person = context.getBean("person", Person.class);
person.order();
}
/**
* 输出:
* 你好,服务员
* 可以给我一个汉堡包么?
*/
}
原文:https://www.cnblogs.com/freshchen/p/12057465.html