07_注解与动态代理

注解

什么是注解
  • 注解(Annotation),就是 Java 代码里面的特殊标记,例如 @Override、@Test 等
  • 作用:让其他程序根据注解信息来决定怎么执行该程序
  • 注意:注解可以用在类上、构造器上、方法上、成员变量上、参数上…
  • 注解的本质是一个接口,Java 中所有注解都是继承了 Annotation 接口的
  • @注解(…) 其实就是一个实现类对象,实现了该注解以及 Annotation 接口
自定义注解
// 自定义注解
public @interface MyTest {String aaa();boolean bbb() default true;String[] ccc();
}
// 方法部分
@MyTest(aaa = "Jack", ccc = {"Java", "HTML"})
public void run() {}

特殊属性名:value——如果注解中只有一个 value 属性,使用注解时,value 名称可以不写!

public @interface MyTest {String value();  // 特殊属性
}
public @interface MyTest {String value();  // 特殊属性int age() default 23;  // 当有默认值时候,可以不删除此行
}
@MyTest("Jack")
public void run() {}
元注解
  • 元注解指的是:修饰注解的注解
@Target(ElemeElenntType.TYPE)作用:声明被修饰的注解只能在哪些位置使用
TYPE类,接口
FIELD成员变量
METHOD成员方法
PARAMETER方法参数
CONSTRUCTOR构造器
LOCAL_VARIABLE局部变量
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;@Target({ElemeElenntType.TYPE,ElementType.METHOD})  // 当前被修饰的注解只能用在类和成员方法上
public @interface MyTest {
}
@Retention(RetentionPolicy.RUNTIME)作用:声明注解的保留周期
SOURCE只作用在源码阶段,字节码文件中不存在
CLASS(默认值)保留到字节码文件阶段,运行阶段不存在
RUNTIME(开发常用)一直保留到运行阶段
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.TYPE, ElementType.METHOD})  // 当前被修饰的注解只能用在类和成员方法上
@Retention(RetentionPolicy.RUNTIME)  // 控制下面的注解一直保留到运行时
public @interface MyTest {
}
注解的解析

什么是注解的解析?

  • 就是判断类上、方法上、成员变量上是否存在注解,并把注解里的内容给解析出来

如何解析注解?

  • 思想:要解析谁上面的注解,就应该先拿到谁
// 自定义注解import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {String value();double aaa() default 100;String[] bbb();
}
// 在类和方法上使用注解@MyTest(value = "Jack", aaa = 99.8, bbb = {"Java", "HTML"})
public class Demo {public static void main(String[] args) {}@MyTest(value = "Tony", aaa = 88.6, bbb = {"java", "html"})public void run() {}
}
// 解析类上的注解import org.junit.Test;
import java.util.Arrays;
public class AnnotationTest {@Testpublic void parseClass() {// 1. 先得到 Class 对象Class c = Demo.class;// 2. 解析类上的注解// 判断这个类上是否包含了某个注解if (c.isAnnotationPresent(MyTest.class)) {MyTest myTest = (MyTest) c.getDeclaredAnnotation(MyTest.class);System.out.println(myTest.value());System.out.println(myTest.aaa());System.out.println(Arrays.toString(myTest.bbb()));}}
}
/*
运行结果:Jack99.8[Java, HTML]*/
// 解析方法上的注解import org.junit.Test;
import java.lang.reflect.Method;
import java.util.Arrays;public class AnnotationTest {@Testpublic void parseMethod() throws Exception {// 1. 先得到 Class 对象,然后通过 Class 对象获取方法对象Class c = Demo.class;Method m = c.getDeclaredMethod("run");// 2. 解析方法上的注解// 判断这个方法上是否包含了某个注解if (m.isAnnotationPresent(MyTest.class)) {MyTest myTest = (MyTest) m.getDeclaredAnnotation(MyTest.class);System.out.println(myTest.value());System.out.println(myTest.aaa());System.out.println(Arrays.toString(myTest.bbb()));}}
}
/*
运行结果:Tony88.6[java, html]*/
应用场景

案例:模拟 Junit 框架

// 需求:定义若干个方法,只要加了MyTest注解,就会触发该方法的执行
/*  分析:1.定义一个自定义注解 MyTest,只能注解方法,存活范围是一直都在2.定义若干个方法,部分方法加上 @MyTest 注解修饰,部分方法不加3.模拟一个 Junit 程序,可以触发加了 @MyTest 注解的方法执行
*/
// 自定义注解部分import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)  // 注解只能注解方法
@Retention(RetentionPolicy.RUNTIME)  // 让当前注解可以一直存活着
public @interface MyTest {}
// 模拟框架部分import java.lang.reflect.Method;public class AnnotationTest {public void test1() {System.out.println("===test1===");}@MyTestpublic void test2() {System.out.println("===test2===");}public void test3() {System.out.println("===test3===");}@MyTestpublic void test4() {System.out.println("===test4===");}public static void main(String[] args) throws Exception {AnnotationTest a = new AnnotationTest();// 启动程序!// 1. 得到 Class 对象Class c = AnnotationTest.class;// 2. 提取这个类中的全部成员方法Method[] methods = c.getDeclaredMethods();// 3. 遍历,获取到每个方法对象,看看其方法上是否存在 @MyTest 注解// 如果存在,则触发该方法执行for (Method method : methods) {if (method.isAnnotationPresent(MyTest.class)) {method.invoke(a);  // 触发当前方法执行}}}
}
/*
运行结果:===test2======test4===*/

动态代理

代理:将一些通用部分的代码提取出来,交给代理去实现(类比 Python 的装饰器)
// 创建一个明星类(前置工作)// 明星(类)
public class Star implements Agent {private String name;public Star(String name) {this.name = name;}// 唱歌方法public String sing(String title) {System.out.println(this.name + "正在唱" + title);return "Think everyone!";}// 跳舞方法public void dance() {System.out.println(this.name + "正在跳舞");}
}
// 创建一个代理人接口(前置工作)// 代理人(接口)
public interface Agent {String sing(String name);void dance();
}
// 创建一个工具类,即:能制作出"代理人"的公司(前置工作)import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// 中介公司(类)
public class ProxyUtil {// 创建代理对象的静态方法public static Agent createProxy(Star sss) {/*public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)参数一:用于指定一个类加载器参数二:指定生成的代理长什么样子,也就是有哪些方法参数三:用来指定生成的代理对象要干什么事情*/Agent starProxy = (Agent) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),  // 参数一new Class[]{Agent.class},  // 参数二new InvocationHandler() {  // 参数三@Override  // 回调方法public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 代理对象要做的事情,请在这里写代码if (method.getName().equals("sing")) {System.out.println("准备话筒,收钱20W");} else if (method.getName().equals("dance")) {System.out.println("准备场地,收钱99W");}return method.invoke(sss, args);}});return starProxy;  // 本静态方法的最后是————返回创建好的"代理对象"}
}
// 调用工具类,让公司为某个明星对象去定制一个专属代理人(正式部分)public class Test {public static void main(String[] args) {// 创建一个明星,叫"迈克尔-杰克逊"Star star = new Star("Michael-Jackson");// 为"迈克尔-杰克逊"创建一个代理人Agent agent = ProxyUtil.createProxy(star);System.out.println(agent.sing("新年好"));  // 让代理人安排他唱歌System.out.println("-----------------");agent.dance();  // 让代理人安排他跳舞}
}/* 运行结果:准备话筒,收钱20WMichael-Jackson正在唱新年好Think everyone!-----------------准备场地,收钱99WMichael-Jackson正在跳舞*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/194971.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQLserver通过字符串中间截取然后分组

当我们存的数据是json的时候可以全部取出在模糊查询但是有多个重复数据的时候就没办法准确的模糊出来这个时候我们就需要用的字符串截取 --创建函数create FUNCTION [dbo].[Fmax] (str varchar(50),start VARCHAR(50),length VARCHAR(50)) RETURNS varchar(max) AS BEGINDEC…

Spring MVC学习随笔-文件下载和上传(配置文件上传解析器multipartResolver)

学习视频&#xff1a;孙哥说SpringMVC&#xff1a;结合Thymeleaf&#xff0c;重塑你的MVC世界&#xff01;&#xff5c;前所未有的Web开发探索之旅 学习视频&#xff1a;【编程不良人】继spring之后快速入门springmvc,面对SpringMVC不用慌 六、SpringMVC 文件上传下载 6.1 文件…

【最通用版FPGA 实现 SPI 驱动】

最近研究了一下SPI协议的FPGA实现&#xff0c;发现网上很多大佬分享的方法都是针对某一特定的flash芯片或者某一传感器芯片来设计电路结构的。所以想根据SPI&#xff08;Serial Peripheral Interface&#xff09;的基本通讯协议实现一个通用版的SPI Master驱动。SPI在嵌入式领域…

同源策略与跨域

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 不论个人练习还是实际开…

【PUSDN】centos查看日志文件内容,包含某个关键字的前后5行日志内容,centos查看日志的几种方法

简述 centos查看日志的几种方法 centos查看日志文件内容&#xff0c;包含某个关键字的前后5行日志内容 前情提示 系统&#xff1a; 一说 部分截图、链接等因过期、更换域名、MD语法等可能不显示&#xff0c;可联系反馈&#xff08;备注好博文地址&#xff09;&#xff0c…

HR看好的字符函数和字符串处理函数!!!

本篇会加入个人的所谓‘鱼式疯言’❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言,而是理解过并总结出来通俗易懂的大白话,我会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的&#xff0c;可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 前言 在本篇…

mybatis整合(手动添加jar包方式)

操作步骤 创建数据库 建立user表 放入数据 1、创建javaweb工程并添加Jar包 用到的jar包 junit 用于测试 mybatis框架&#xff1a;mybatis-3.5.9.jar mysql数据库&#xff1a;mysql-connector-java-8.0.28.jar 2、添加MyBatis核心配置文件 <?xml version"1.0"…

Leetcode刷题详解——乘积为正数的最长子数组长度

1. 题目链接&#xff1a;1567. 乘积为正数的最长子数组长度 2. 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;请你求出乘积为正数的最长子数组的长度。 一个数组的子数组是由原数组中零个或者更多个连续数字组成的数组。 请你返回乘积为正数的最长子数组长度。 示…

什么是结构化数据?哪些OCR软件可将图片文字转为结构化数据?

结构化数据是指按照一定的数据模型组织和存储的数据&#xff0c;具有明确的数据类型和数据关系&#xff0c;并且可通过计算机程序进行处理和分析。这种数据通常存储在定义明确的模式中&#xff0c;例如数据库&#xff0c;采用表格的形式存储&#xff0c;每个数据项都有特定的字…

Mover Creator 用户界面

1 “开始”对话框 首次打开 Mover Creator 时&#xff0c;出现的第一个页面是“开始”对话框&#xff0c;如下所示。从这里开始&#xff0c;用户可以选择开始设计飞机、武器或发动机。在上述每种情况下&#xff0c;用户都可以创建新模型或编辑现有模型。 1.1 新建模型 如果用…

Apache Doris 详细教程(二)

5、doris的查询语法 5.1、doris查询语法整体结构 SELECT [ALL | DISTINCT | DISTINCTROW ] -- 对查询字段的结果是否需要去重&#xff0c;还是全部保留等参数 select_expr [, select_expr ...] -- select的查询字段 [FROM table_references [PARTITION…

94基于matlab的蚁群算法 (ACO) 对付的图像边缘检测问题

基于matlab的蚁群算法 (ACO) 对付的图像边缘检测问题。提出基于蚁群算法的边缘检测方法是能够建立一个信息素矩阵表示提出了一种在图像每个像素位置的边缘信息根据大量的蚂蚁的运动有哪些派去在图像上移动。此外&#xff0c;运动这些蚂蚁是由图像的局部变化驱动强度值。数据可更…

U1编译概述

文章目录 基本概念定义一些概念 编译流程词法分析语法分析语义分析、生成中间代码中间代码 代码优化生成目标程序五个阶段中都需要做的两件事符号表管理出错处理 总结 其他概念多层中间表示和遍&#xff08;PASS&#xff09;三端模式课程概述 基本概念 定义 用高级语言编制的…

【Java 基础】18 I/O流

文章目录 1.基本概念2.字节流3.字符流4.标准输入输出5.最佳实践 I/O流&#xff08;Input/Output 流&#xff09;是计算机程序中不可或缺的一部分&#xff0c; 往大了说所有的操作都是IO。Java 提供了强大而灵活的 I/O 框架&#xff0c;支持各种数据的 读取和 写入操作。 1.基…

45 - 多线程性能优化常见问题

1、使用系统命令查看上下文切换 上下文切换常见的监测工具 1.1、Linux 命令行工具之 vmstat 命令 vmstat 是一款指定采样周期和次数的功能性监测工具&#xff0c;我们可以使用它监控进程上下文切换的情况。 vmstat 1 3 命令行代表每秒收集一次性能指标&#xff0c;总共获取 …

day5 两数之和为x

vector<int> twoSum(vector<int>& nums, int target) { std::unordered_map <int,int> map; for(int i 0; i < nums.size(); i) { // 遍历当前元素&#xff0c;并在map中寻找是否有匹配的key auto iter map.find(target - nums[i]); if(iter ! map…

【JavaSE】:String(二):深入String

深入String 一.字符串的存储二.字符串的不可变性三.字符串修改四.StringBuilder和StringBuffer 一.字符串的存储 我们知道双引号里的数据都是字符串常量&#xff0c;储存在字符串常量池当中。 例子 直接使用是比较地址。字符串常量池有一个特点&#xff1b;它会先检查该常量是否…

LLM-Intro to Large Language Models

LLM some LLM’s model and weight are not opened to user what is? Llama 270b model 2 files parameters file parameter or weight of neural networkparameter – 2bytes, float number code run parameters(inference) c or python, etcfor c, 500 lines code withou…

智能制造热点词汇科普篇——LaaS、SaaS、PaaS

随着智能制造的不断普及&#xff0c;越来越多的制造企业选择进行数字化转型增强自身的综合竞争力。自动化、信息化、智能化是实现数字化转型的三个重要步骤&#xff0c;在进行对企业的充分调研后&#xff0c;选择适合自己的自动化设备、信息化软件&#xff0c;最后与各种智能化…

中介者模式 rust和java的实现

文章目录 中介者模式介绍实现javarustrust仓库 中介者模式 中介者模式&#xff08;Mediator Pattern&#xff09;又被称为 调停者模式 。 它定义了一个中介对象来封装一系列对象之间的交互关系。 中介者使各个对象之间不需要显式地相互引用&#xff0c;从而使耦合性降低&#…