当前位置: 首页 > news >正文

网站空间ip需不需要备案/技术短期培训班

网站空间ip需不需要备案,技术短期培训班,网站制作论文优帮云,做美食网站的意义Java反射自定义注解底层设计原理一、反射机制1.1、什么是反射1.2、反射机制的优缺点1.3、反射的用途1.4、反射技术的使用1.5、反射常用的API1.6、运行期间,一个类,只有一个Class对象产生1.7、反射执行构造函数1.7.1、执行无参数构造函数1.7.2、执行有参数…

Java反射自定义注解底层设计原理

  • 一、反射机制
    • 1.1、什么是反射
    • 1.2、反射机制的优缺点
    • 1.3、反射的用途
    • 1.4、反射技术的使用
    • 1.5、反射常用的API
    • 1.6、运行期间,一个类,只有一个Class对象产生
    • 1.7、反射执行构造函数
      • 1.7.1、执行无参数构造函数
      • 1.7.2、执行有参数构造函数
    • 1.8、反射执行给属性赋值
      • 1.8.1、反射执行给公有属性赋值
      • 1.8.2、反射执行给私有属性赋值
    • 1.9、反射执行调用方法
      • 1.9.1、反射调用公有方法
      • 1.9.2、反射调用私有方法
      • 1.9.3、反射调用方法传递参数
      • 1.9.4、通过反射越过泛型检查
  • 二、注解
    • 2.1、注解概念
      • 2.1.1、什么是注解
      • 2.1.2、常用注解
      • 2.1.3、元注解
      • 21.4、常用注解
      • 2.1.5、注解的Target
    • 2.2、获取注解信息
    • 2.3、注解如何生效
    • 2.4、自定义限流注解实现案例

一、反射机制

1.1、什么是反射

通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。程序中一般的对象的类型都是在编译期就确定下来的,而 Java 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。

(1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。

(2)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

使用反射机制可以动态获取当前class的信息 比如方法的信息、注解信息、方法的参数、属性等;

1.2、反射机制的优缺点

第三方框架—创建对象 不是直接new 反射机制创建

目的:提供开发者能够更好封装框架实现扩展功能。

在一个类中 定义了一个私有属性/方法 反射机制破解私有属性

优点:

  • 在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。

缺点:

  • 反射会消耗一定的系统资源,因此如果不需要动态地创建一个对象,那么就不需要用反射;
  • 反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

1.3、反射的用途

反编译:.class–>.java
1.通过反射机制访问java对象的属性,方法,构造方法等
2.JDBC加载驱动连接 class.forname

Class.forName("com.mysql.jdbc.Driver"); // 动态加载mysql驱动

3.Spring容器框架IOC实例化对象

<bean id="mayikt" class="com.mayikt.UserEntity" />

4.自定义注解生效(反射+Aop)
5.第三方核心的框架 mybatis orm

1.4、反射技术的使用

Class类 代表类的实体,在运行的Java应用程序中表示类和接口

Field类 代表类的成员变量(成员变量也称为类的属性)

Method类 代表类的方法

Constructor类 代表类的构造方法

  • getField、getMethod和getCostructor方法可以获得指定名字的域、方法和构造器。
  • getFields、getMethods和getCostructors方法可以获得类提供的public域、方法和构造器数组,其中包括超类的共有成员。
  • getDeclatedFields、getDeclatedMethods和getDeclaredConstructors方法可以获得类中声明的全部域、方法和构造器,其中包括私有和受保护的成员,但不包括超类的成员。

1.5、反射常用的API

(1)Object–>getClass
(2)任何数据类型(包括基本的数据类型)都有一个“静态”的class属性
(3)通过class类的静态方法:forName(String className)(最常用)

Class<?> aClass = Class.forName("com.java521.domain.User");

User

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class User {private String username;private Integer Integer;
}

Test01

public class Test01 {public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {//1.第一种获取class方式User user = new User();Class userClass1 = user.getClass();// 默认执行无参构造函数User user2 = (User) userClass1.newInstance();// 2.第二种方式 直接获取classClass userClass2 = User.class;User user3 = (User) userClass2.newInstance();System.out.println("user3 = " + user3);// 3.第三种方式 类的完整路径地址Class userClass3 = Class.forName("com.java521.domain.User");User user4 = (User) userClass3.newInstance();System.out.println("user4 = " + user4);}
}

1.6、运行期间,一个类,只有一个Class对象产生

public class Test02 {public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {//1.第一种获取class方式User user = new User();Class userClass1 = user.getClass();// 2.第二种方式 直接获取classClass userClass2 = User.class;// 3.第三种方式 类的完整路径地址Class userClass3 = Class.forName("com.java521.domain.User");System.out.println(userClass3);System.out.println(userClass1 == userClass2);System.out.println(userClass1 == userClass3);}
}

1.7、反射执行构造函数

1.7.1、执行无参数构造函数

Class userClass = Class.forName("com.java521.domain.User");
User user = (User) userClass.newInstance();
System.out.println(user);

1.7.2、执行有参数构造函数

Class userClass = Class.forName("com.java521.domain.User");
Constructor constructor = userClass.getConstructor(String.class, Integer.class);
User user = (User) constructor.newInstance("java521", 25);
System.out.println(user);

1.8、反射执行给属性赋值

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class User {private String username;private Integer Integer;//公有public Integer sex;
}

1.8.1、反射执行给公有属性赋值

//给公有属性赋值
Class userClass = Class.forName("com.java521.domain.User");
Field sex = userClass.getField("sex");
User user = (User) userClass.newInstance();
sex.set(user, 1);
System.out.println(user);

1.8.2、反射执行给私有属性赋值

//给私有属性赋值
Class userClass = Class.forName("com.java521.domain.User");
User user = (User) userClass.newInstance();
Field username = userClass.getDeclaredField("username");
// 设置允许访问私有属性
username.setAccessible(true);
username.set(user, "xiaoming");
System.out.println(user);

注意

Exception in thread "main" java.lang.IllegalAccessException: Class com.java521.controller.Test06 can not access a member of class com.java521.domain.User with modifiers "private"at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)at java.lang.reflect.Field.set(Field.java:761)at com.java521.controller.Test06.main(Test06.java:22)// 解决办法: 
// 设置允许访问私有属性
username.setAccessible(true);

1.9、反射执行调用方法

User

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class User {private String username;private Integer Integer;public Integer sex;public void publicFucntion() {System.out.println("我是公有方法");}private void privateFucntion() {System.out.println("我是私有方法");}private Integer sum(Integer val1, Integer val2) {return val1 + val2;}
}

1.9.1、反射调用公有方法

//反射调用公有方法
User user = (User) userClass.newInstance();
Method publicFucntion = userClass.getDeclaredMethod("publicFucntion");
publicFucntion.invoke(user);

1.9.2、反射调用私有方法

//反射调用私有方法
Class userClass = Class.forName("com.java521.domain.User");
User user = (User) userClass.newInstance();
Method privateFucntion = userClass.getDeclaredMethod("privateFucntion");
privateFucntion.setAccessible(true);
privateFucntion.invoke(user);

1.9.3、反射调用方法传递参数

//反射调用方法传递参数
Class userClass = Class.forName("com.java521.domain.User");
User user = (User) userClass.newInstance();
Method sum = userClass.getDeclaredMethod("sum", Integer.class, Integer.class);
sum.setAccessible(true);
Integer result = (Integer) sum.invoke(user, 3, 4);
System.out.println(result);

1.9.4、通过反射越过泛型检查

泛型用在编译期,编译过后泛型擦除(消失掉),所以是可以通过反射越过泛型检查的

public class Test10 {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {List<String> strings = new ArrayList<String>();strings.add("java");Class<? extends List> aClass = strings.getClass();Method add = aClass.getDeclaredMethod("add", Object.class);Object invoke = add.invoke(strings, 1);System.out.println(strings);}
}

二、注解

2.1、注解概念

2.1.1、什么是注解

注解用来给类声明附加额外信息,可以标注在类、字段、方法等上面,编译器、JVM以及开发人员等都可以通过反射拿到注解信息,进而做一些相关处理

SpringBoot 全部都是采用注解化

2.1.2、常用注解

@Override 只能标注在子类覆盖父类的方法上面,有提示的作用

@Deprecated 标注在过时的方法或类上面,有提示的作用

@SuppressWarnings(“unchecked”) 标注在编译器认为有问题的类、方法等上面,用来取消编译器的警告提示,警告类型有serial、unchecked、unused、all

2.1.3、元注解

元注解用来在声明新注解时指定新注解的一些特性

@Target 指定新注解标注的位置,比如类、字段、方法等,取值有ElementType.Method等

@Retention 指定新注解的信息保留到什么时候,取值有RetentionPolicy.RUNTIME等

@Inherited 指定新注解标注在父类上时可被子类继承

21.4、常用注解

@Target(ElementType.METHOD) // 指定新注解可以标注在方法上

@Retention(RetentionPolicy.RUNTIME) // 指定新注解保留到程序运行时期

@Inherited // 指定新注解标注在父类上时可被子类继承

public @interface MayiktName {public String name();
}

自定义注解 运行 :反射+aop

2.1.5、注解的Target

Target解释
TYPE类、接口(包括注解类型)和枚举的声明
FIELD字段声明(包括枚举常量)
METHOD方法声明
PARAMETER参数声明
CONSTRUCTOR构造函数声明
LOCAL_VARIABLE本地变量声明
ANNOTATION_TYPE注解类型声明
PACKAGE包声明
TYPE_PARAMETER类型参数声明,JavaSE8引进,可以应用于类的泛型声明之处
TYPE_USEJavaSE8引进,此类型包括类型声明和类型参数声明

2.2、获取注解信息

Java521

@Target({ElementType.METHOD,ElementType.TYPE,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Java521 {
}

User

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Java521
public class User {private String username;private Integer Integer;public Integer sex;public void publicFucntion() {System.out.println("我是公有方法");}private void privateFucntion() {System.out.println("我是私有方法");}private Integer sum(Integer val1, Integer val2) {return val1 + val2;}private void add(Integer val) {System.out.println("val = " + val);}@Java521public void loveJava() {System.out.println("my love java");}
}

Test01

public class Test01 {public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {// 1.获取当前类上的注解Class<?> userClass = Class.forName("com.java521.domain.User");Annotation annotation1 = userClass.getDeclaredAnnotation(Java521.class);System.out.println("annotation1 = " + annotation1);// 2.获取方法上的注解User user = (User) userClass.newInstance();Method loveJava = userClass.getDeclaredMethod("loveJava");// 执行方法loveJava.invoke(user);Annotation annotation2 = loveJava.getDeclaredAnnotation(Java521.class);System.out.println("annotation2 = " + annotation2);// 3.获取属性上的注解 没有注解 为nullField sex = userClass.getDeclaredField("sex");Annotation annotation3 = sex.getDeclaredAnnotation(Java521.class);System.out.println("annotation3 = " + annotation3);// 4.获得构造方法注解 没有注解 为null//先获得构造方法对象Constructor<?> constructor = userClass.getConstructor(new Class[]{});Annotation annotation4 = constructor.getAnnotation(Java521.class);System.out.println("annotation4 = " + annotation4);}
}

2.3、注解如何生效

实际项目中 注解想生效通过反射+aop机制

2.4、自定义限流注解实现案例

maven

<dependencies><!--  springboot 整合web组件--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>18.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency>
</dependencies><dependencies><!--  springboot 整合web组件--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>18.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency></dependencies>

使用自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JavaCurrentLimit {/*** name 限流的名称** @return*/String name() default "";/*** 每秒能够允许访问的次数 20 底层* 令牌桶** @return*/double token() default 20;
}

整合Aop实现接口限流

@Aspect
@Component
public class CurrentLimitAop {/*** 每秒生成1.0个令牌 每s产生10 token*/
//    private RateLimiter rateLimiter = RateLimiter.create(1);private ConcurrentHashMap<String, RateLimiter> rateLimiters = new ConcurrentHashMap();@Around(value = "@annotation(com.java521.example.JavaCurrentLimit)")public Object around(ProceedingJoinPoint joinPoint) {try {//获取拦截的方法名Signature sig = joinPoint.getSignature();//获取拦截的方法名MethodSignature methodSignature = (MethodSignature) sig;// 判断方法上是否有加上该注解,如果有加上注解则限流JavaCurrentLimit javaCurrentLimit =methodSignature.getMethod().getDeclaredAnnotation(JavaCurrentLimit.class);if (javaCurrentLimit == null) {// 执行目标方法return joinPoint.proceed();}// 获取注解上的nameString name = javaCurrentLimit.name();// 获取注解上的tokendouble token = javaCurrentLimit.token();RateLimiter rateLimiter = rateLimiters.get(name);if (rateLimiter == null) {rateLimiter = RateLimiter.create(token);rateLimiters.put(name, rateLimiter);}// 开始限流boolean result = rateLimiter.tryAcquire();if (!result) {return "当前访问人数过多,请稍后重试!";}return joinPoint.proceed();} catch (Throwable throwable) {return "系统出现了错误!";}}
}

使用效果

@RestController
public class MemberController {/*** 每秒生成1.0个令牌*/@GetMapping("/get")@JavaCurrentLimit(name = "get", token = 1)public String get() {
//        boolean result = rateLimiter.tryAcquire();
//        if (!result) {
//            return "当前访问人数过多,请稍后重试!";
//        }return "my is get";}@GetMapping("/add")@JavaCurrentLimit(name = "add", token = 10)public String add() {return "my is add";}@GetMapping("/my")public String my() {return "my is add";}
}

http://127.0.0.1:8080/get
http://127.0.0.1:8080/my

http://www.lbrq.cn/news/1586503.html

相关文章:

  • 定制高端网站/汉川seo推广
  • 请问做网站需要什么软件/友情链接检测
  • 绞铜机 东莞网站建设/今日头条军事新闻
  • 网站选项卡如何做自适应/搜索引擎营销的模式有哪些
  • 手机网站jquery底部导航菜单/深圳海外推广
  • java mysql 网站建设/今日热点新闻事件简介
  • 淘宝优惠券网站怎么做 知乎/seo深圳培训班
  • 联图二维码生成器/网站seo技术
  • 昌乐网站建设/青岛最新消息
  • 国外建设网站流程/百度竞价排名广告
  • 青岛公司网站建设/站长工具网
  • 北京网站建设的价格天/seo对网店推广的作用
  • 做卖挖掘机的网站/搜狗推广登录平台官网
  • 网络营销的理论基础有哪些/seo sem什么意思
  • 怎么做直播室的网站/大连网站优化
  • 给政府做网站/品牌营销策划包括哪些内容
  • 网站网页设计模板下载/互联网广告平台有哪些
  • 本科学计算机是做网站吗/湖南产品网络推广业务
  • web网站开发用什么软件/手机网站怎么优化关键词
  • 企业网站建设 法规/打开百度搜索引擎
  • 没有公司个人可以做网站卖东西吗/潍坊seo教程
  • 赤峰网站建设red/如何做网站推广
  • 手表网站布局/成都网站关键词推广
  • php做的静态网站怎么加密/seo优化思路
  • 公司做网站需要准备什么资料/app推广平台
  • 济南网站建设网站制作/电商网站怎样优化
  • bob网站建设/伟哥seo博客
  • 哈尔滨网站建设价格低/seo全国最好的公司
  • 课程网站建设/企业网站建设论文
  • wordpress图片付费主题/北京seo优化诊断
  • 2025最新版天猫图片搜索API全解析:从图像识别到商品匹配实战
  • Numpy科学计算与数据分析:Numpy数组操作入门:合并、分割与重塑
  • 全栈:如何操作在SQLserver里面CRUD(增删改查)
  • 数据结构(五):顺序循环队列与哈希表
  • TSMaster-C小程序使用
  • 消息队列的优缺点