注解概述
注解概述、作用
- Java注解(Annotation)又称为Java标注,是JDK5.0引入的一种注释机制
- Java语言中的类、构造器、方法、成员变量、参数等都可以被注解标注
注解的作用是什么?
- 对于Java中类、方法、成员变量做标记,然后进行特殊处理,以至于到底作何种处理由业务需求来决定
- 例如:Junit框架中,标记了注解@Test的方法就可以被当作测试方法执行,而没有标记的就不能当成测试方法执行
自定义注解
自定义注解---格式
- 自定义注解就是自己做一个注解来使用。
public @interface 注解名称{
public 属性类型 属性名() default 默认值;
//属性类型--java支持的数据类型基本上都支持
}
/**
* 目标:学会自定义注解。掌握其定义的格式和语法
*/
@Test01(name = "精通Javase",authors = "法外狂徒",price = 1200)
public class AnnotationDone1 {
@Test01(name = "精通Javase2",authors = "法外狂徒",price = 1200)
public AnnotationDone1(){
}
@Test01(name = "精通Javase1",authors = "法外狂徒",price = 1200)
public static void main(String[] args) {
@Test01(name = "精通Javase",authors = "法外狂徒",price = 1200)
int age = 22;
}
}
特殊属性
- value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写
- 但是如果有多个属性,且多个属性没有默认值,那么value名称是不能省略的。
元注解
- 元注解:就是注解注解的注解。
元注解有两个:
- @Target:约束自定义注解只能在哪种地方使用
- @Retention:申明注解的生命周期
@Target中可使用的值定义在ElenmentType枚举类中,常用值如下
- TYPE,类,接口
- FIELD,成员变量
- METHOD,成员方法
- PARAMETER,方法参数
- CONSTRUCTOR,构造器
- LOCAL_VARIABLE,局部变量
@Retention中可使用的值定义在R儿疼体哦那Policy枚举类中,常用值如下
- SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在
- CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值
- RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段(开发常用)
注解解析
注解的解析
- 注解的操作中经常需要进行解析,注解的解析就是判断是否存在注解,存在注解就解析出内容
与注解解析相关的接口
- Annotation:注解的顶级接口,注解都是Annotation类型的对象
- AnnotationElement:该接口定义了与注解解析相关的解析方法
方法 说明 Annotation[] getDeclaredAnnotations() 获得当前对象上使用的所有注解,返回注解数组 T getDeclaredAnnotation(Class<T> annotationClass) 根据注解类型获取对应注解对象 boolean isAnnotationPresent(Class<Annotation> annotationClass) 判断当前第项是否使用了指定的注解,如果使用了则返回true,否则返回false -
所有的类成分Class,Method,Field,Construor,都是先了AnnotationElement接口,他们都拥有解析注解的能力
解析注解的技巧
- 注解在哪个成分上,就先拿哪个成分对象
- 比如注解作用成员方法,则要获得该成员方法对应的Method对象,在拿上面的注解
- 注解作用在类上,则要该类的Class对象,再拿上面的注解
- 注解作用在成员变量上,则要获得该成员变量对应的Field对象,在来拿上面的注解
注解的应用场景一:junit框架
模拟Junit框架
需求
- 定义若干个方法,只要加了MyTest注解,就可以在启动时被触发执行
分析
- 定义一个自定义注解MyTest,只能注解方法,存活范围是一直都在
- 定义若干个方法,只要有@MyTest注解的方法就能在启动时被触发执行,没有这个注解方法不能执行。
MyTest
// 注解方法, 注解成员变量
@Target({ElementType.METHOD,ElementType.FIELD}) //元注解
@Retention(RetentionPolicy.RUNTIME)//一直存在,在运行阶段这个注解也不会消失
public @interface MyTest {
}
public class AnnotationDome4 {
@MyTest
public void test1(){
System.out.println("=========测试一==========");
}
public void test2(){
System.out.println("=========测试二==========");
}
@MyTest
public void test3(){
System.out.println("=========测试三==========");
}
public static void main(String[] args) throws Exception{
AnnotationDome4 annot = new AnnotationDome4();
//1.获取类对象
Class c = AnnotationDome4.class;
//2.提取全部方法
Method[] methods = c.getDeclaredMethods();
//3.遍历方法,得到Mytest对象
for (Method method : methods) {
if (method.isAnnotationPresent(MyTest.class)){
method.invoke(annot);
}
}
}
}
动态代理
什么是代理?
- 代理指:某些场景下对象会找一个代理对象,来辅助自己完成一些工作,如歌星(经纪人)
代理主要是对对象的行为额外做一些辅助操作
如何创建代理对象
- Java中代理的代表类是:java.long.reflect.Proxy
- Proxy提供了一个静态方法,用于为对象产生一个代理对象返回
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 为对象返回一个代理对象
参数一:定义代理类的类加载器
参数二:代理类要实现的接口列表
参数三:将方法调用分派的处理程序。(代理对象的核心处理程序)
代理是什么?
- 一个对象,用来对被代理对象的行为额外做的一些辅助工作
在Java中实现动态代理的步骤是什么样的?
- 必须存在接口
- 被代理对象需要实现接口
- 使用Proxy类提供的方法,对象的代理对象
通过代理对象调用方法,执行流程是什么样的?
- 先走向代理
- 代理可以为方法额外做一些辅助工作
- 开发真正触发对象的方法的执行
- 回到代理中,由代理负责返回结果给方法的调用者
动态代理的优点
- 可以在不改变源码的情况下,实现对象功能的增强,提高了代码的复用
- 简化编程工作、提高了开发效率,同时提高了软件的可拓展性。
- 可以为被还你对象的所有方法做代理。
- 非常的灵活,支持任意接口类型的实现类对象做代理,也可以直接为接口本身做代理。