问题是最好的老师,让我们带着问题去学习Annotation
来自灵魂深处的三问
注解是什么?注解可以做什么?学完注解对我们有什么帮助?
1.注解是什么?
Annotation是一种源程序中的元素关联任何信息和任何元数据的途径和方法。
jdk中自带了多个注解,接触到比较多的如:
@Override 表示覆盖和重写父类的方法
@Deprecated 表示该方法已经过期不再使用,提醒你更换成新的方法或类
@SuppressWarnings 表示忽略指定警告
第三方常用的注解
Spring 框架中常见的
@Autowired 自动注入注解
@Service 服务注解
@Repository 仓库的注解
@Component @Configuration @Resource 等等
Mybatis 框架中常见的注解
@InsertProvider
@UpdateProvider
@Options
上面回顾了下 注解的概念,以及我们常用的注解,到现在对注解应该有了模糊的了解 ,下面让我们来详细的剖析下注解到底是个什么东西
进入正题
注解相当于是描述数据的元数据
按照注解在程序中存在的阶段 分为三大类:
1、源码注解:注解只在源码中存在,编译成class文件后,不存在
2、编译时注解:注解在源码和.class文件中都存在,jdk自带的注解都是属于编译时注解
3、运行时注解:在程序运行时依然起作用,甚至影响运行逻辑
按照来源分类
1、JDK自带注解
2、第三方注解
3、自定义注解
按照作用分类
1、编写文档
2、代码分析
3、编译检查
jdk提供了4种注解,专门负责注解的创建
@Target 标示该注解用于什么地方
- ElementType 参数有
CONSTRUCTOR :构造器的声明
Field:域声明(包括enum实例)
LOCAL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE:包声明
PARAMETER:参数声明
TYPE:类、接口(包括注解类型) 或ENUM声明
@Retention标示需要在什么级别保存该注解信息,
-RetentionPolicy参数包括
SOURCE:注解被编译后丢弃
CLASS:注解在class文件中丢弃
RUNTIME:VM将在运行期间保留注解,可以通过反射机制读取注解的信息
@Document 将注解包含在Javadoc中
@Inherited 允许自雷继承父类中的注解
2、注解能做什么
总结:
1、java注解是附加在代码中的一些元信息,属于工具,用于在编译、运行时解析和使用,起到说明和配置的功能。
2、注解不会影响代码的实际逻辑,有工具属性,起到辅助性的作用。
下面通过我们自己动手自定义一个Annotation
MyAnnotation 类
@Target({ ElementType.FIELD, ElementType.METHOD,
ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String msg() default "参数不能为空";
}
创建一个Hello 类
public class Hello {
public void sayHello(@MyAnnotation String name,@MyAnnotation String start) {
System.out.println("hello:"+name);
System.out.println(start);
}
}
创建一个代理类HelloCglib
public class HelloCglib implements MethodInterceptor {
private Class target;
public Object getInstance(Class target){
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object object, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
// TODO Auto-generated method stub
System.out.println("我是CGLIB的动态代理");
System.out.println("准备执行");
if(!check(method,objects)) {
System.out.println("无法执行");
return false;
}
Object returnObject = proxy.invokeSuper(object, objects);
return returnObject;
}
/**
* 对参数校验的方法
* @param method 目标方法
* @param objects 相关参数
* @return
*/
private boolean check(Method method, Object[] objects) {
Parameter [] parameters = method.getParameters();
for(int i=0;i<parameters.length;i++) {
Parameter parameter = parameters[i];
if(parameter.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation annotation = parameter.getAnnotation(MyAnnotation.class);
if(objects == null || objects[i]==null) {
System.out.println(parameter.getName()+annotation.msg());
return false;
}
}
}
return true;
}
}
写一个测试类 进行测试
public class HelloTest {
@Test
public void test() {
HelloCglib helloCglib = new HelloCglib();
Hello proxy = (Hello)helloCglib.getInstance(Hello.class);
proxy.sayHello("word", null);
fail("Not yet implemented");
}
}
通过上面例子,相信我们更加深入了解了Annotation能做什么了
3、学完注解对我们有什么帮助
1、可以利用Annotation的特性,来自定义Annotation,帮助我们解决开发中遇到的问题
2、可以帮助我们更好的去理解那些优秀的第三方框架的底层实现原理
在学习中遇到相关问题的同仁,欢迎留言,一起学习,一起进步
网友评论