那种投票网站里面怎么做,昆明做公司官网的公司,wordpress评论通知作者,网络服务提供者不得为未满多少岁开展工作文章目录一、反射1. 反射概念2. 反射机制的优缺点3. 反射的用途4. 反射技术的使用5. 反射常用的Api6. 反射执行构造函数7. 反射执行给属性赋值8. 反射执行调用方法二、注解2.1. 注解概念2.2. 常用注解2.3. 元注解2.4. 常用注解2.5. 注解的Target2.6. 获取注解信息2.7. 注解如何…
文章目录一、反射1. 反射概念2. 反射机制的优缺点3. 反射的用途4. 反射技术的使用5. 反射常用的Api6. 反射执行构造函数7. 反射执行给属性赋值8. 反射执行调用方法二、注解2.1. 注解概念2.2. 常用注解2.3. 元注解2.4. 常用注解2.5. 注解的Target2.6. 获取注解信息2.7. 注解如何生效2.8. 注解实现案例2.09. 封装自定义注解限流框架2.10. 整合Aop实现接口限流2.11. 案例1.什么是反射、反射优缺点 2.反射的用途/反射应用场景 3.反射调用方法/给属性赋值 4.反射如何越过泛型检查 5.什么是注解/注解生效的原理 6.自定义注解实现API接口限流框架
一、反射
1. 反射概念
使用反射机制可以动态获取当前class的信息 比如方法的信息、注解信息、方法的参数、属性等。 .java 源代码 编译.class 类加载器 jvm 字节码
2. 反射机制的优缺点
优点提供开发者能够更好封装框架实现扩展功能。 缺点 1反射会消耗一定的系统资源因此如果不需要动态地创建一个对象那么就不需要用反射 2反射调用方法时可以忽略权限检查因此可能会破坏封装性而导致安全问题。
3. 反射的用途
反编译.class–.java 1.通过反射机制访问java对象的属性方法构造方法等 2. JDBC加载驱动连接 class.forname Class.forName(“com.mysql.jdbc.Driver”); // 动态加载mysql驱动 3. Spring容器框架IOC实例化对象 bean idmayikt classcom.mayikt.UserEntity /4.自定义注解生效反射Aop 5.第三方核心的框架 mybatis orm
4. 反射技术的使用
Class类 代表类的实体在运行的Java应用程序中表示类和接口 Field类 代表类的成员变量成员变量也称为类的属性 Method类 代表类的方法 Constructor类 代表类的构造方法 1.getField、getMethod和getCostructor方法可以获得指定名字的域、方法和构造器。 2.getFields、getMethods和getCostructors方法可以获得类提供的public域、方法和构造器数组其中包括超类的共有成员。 3.getDeclatedFields、getDeclatedMethods和getDeclaredConstructors方法可以获得类中声明的全部域、方法和构造器其中包括私有和受保护的成员但不包括超类的成员。
5. 反射常用的Api
1Object–getClass (2任何数据类型包括基本的数据类型都有一个“静态”的class属性 3通过class类的静态方法forName(String className)最常用 Class? aClass Class.forName(“com.mayikt.entity.UserEntity”); /*** 反射机制使用的三种方式* p* 第1种获取class UserEntity.class* 第2种获取class Class.forName(类的全路径);* 第3种new UserEntity().getClass()*/Testpublic void objCreateTest() throws InstantiationException, IllegalAccessException, ClassNotFoundException {ClassUserEntity userClass1 UserEntity.class;//默认执行无参构造函数UserEntity userEntity1 userClass1.newInstance();System.out.println(userEntity1);//2.类的的完成路径 报名类名Class? userClass2 Class.forName(com.gblfy.elk.entity.UserEntity);System.out.println(userClass1 userClass2);//3.new UserEntity().getClass()UserEntity userEntity2 new UserEntity();Class userClass3 userEntity2.getClass();System.out.println(userClass1 userClass3);//trueSystem.out.println(userEntity1 userEntity2);//false}运行期间一个类只有一个Class对象产生 6. 反射执行构造函数
执行无参数构造函数和执行有参数构造函数 /*** 使用反射机制初始化对象*/Testpublic void constructorTest() throws InstantiationException, IllegalAccessException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException {// //2.类的的完成路径 报名类名Class? userClass2 Class.forName(com.gblfy.elk.entity.UserEntity);// //默认执行无参构造函数UserEntity userEntity (UserEntity) userClass2.newInstance();System.out.println(userEntity);//执行有参构造函数Constructor? declaredConstructor userClass2.getDeclaredConstructor(String.class, Integer.class);UserEntity userEntity2 (UserEntity) declaredConstructor.newInstance(mayikt, 22);System.out.println(userEntity2);}7. 反射执行给属性赋值
反射执行给公有属性赋值和反射执行给私有属性赋值
/*** 反射如何给属性赋值*/Testpublic void evaluationTest() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {Class? userClass2 Class.forName(com.gblfy.elk.entity.UserEntity);UserEntity userEntity2 (UserEntity) userClass2.newInstance();//给公有属性赋值Field publicName userClass2.getDeclaredField(publicName);publicName.set(userEntity2, mayikt);System.out.println(userEntity2.getPublicName());//给私有属性赋值Field userName userClass2.getDeclaredField(userName);//设置访问私有属性权限userName.setAccessible(true);userName.set(userEntity2, mayikt2);System.out.println(userEntity2.getUserName());}注意
xception in thread main java.lang.IllegalAccessException: Class com.mayikt.test.Test03 can not access a member of class com.mayikt.entity.UserEntity with modifiers privateat 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.mayikt.test.Test03.main(Test03.java:28)
解决办法
// 设置允许访问私有属性
userName.setAccessible(true);
8. 反射执行调用方法
反射调用公有方法 //使用反射机制调用公用无参方法Testpublic void methodNoparamTest() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, InvocationTargetException, NoSuchMethodException {Class? userClass2 Class.forName(com.gblfy.elk.entity.UserEntity);//创建类实例Object o userClass2.newInstance();//获取公有和私有方法Method method userClass2.getDeclaredMethod(mayikt);//设置访问私有方法权限method.setAccessible(true);method.invoke(o);}反射调用私有方法和反射调用方法传递参数
//使用反射机制调用私有有参方法Testpublic void methodCarryParamTest() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, InvocationTargetException, NoSuchMethodException {Class? userClass2 Class.forName(com.gblfy.elk.entity.UserEntity);//创建类实例Object o userClass2.newInstance();//获取公有和私有方法Method method userClass2.getDeclaredMethod(sum, Integer.class, Integer.class);//设置访问私有方法权限method.setAccessible(true);Integer result (Integer) method.invoke(o, 1, 5);System.out.println(result);}二、注解
2.1. 注解概念
什么是注解 注解用来给类声明附加额外信息可以标注在类、字段、方法等上面编译器、JVM以及开发人员等都可以通过反射拿到注解信息进而做一些相关处理
SpringBoot 全部都是采用注解化
2.2. 常用注解
Override 只能标注在子类覆盖父类的方法上面有提示的作用
Deprecated 标注在过时的方法或类上面有提示的作用
SuppressWarnings(unchecked) 标注在编译器认为有问题的类、
方法等上面用来取消编译器的警告提示警告类型有serial、unchecked、unused、all2.3. 元注解
元注解用来在声明新注解时指定新注解的一些特性
Target 指定新注解标注的位置比如类、字段、方法等取值有ElementType.Method等
Retention 指定新注解的信息保留到什么时候取值有RetentionPolicy.RUNTIME等
Inherited 指定新注解标注在父类上时可被子类继承2.4. 常用注解 Target(ElementType.METHOD) // 指定新注解可以标注在方法上
Retention(RetentionPolicy.RUNTIME) // 指定新注解保留到程序运行时期
Inherited // 指定新注解标注在父类上时可被子类继承
public interface MayiktName {public String name();
}
自定义注解 运行 反射aop
2.5. 注解的Target
TYPE类、接口包括注解类型和枚举的声明
FIELD字段声明包括枚举常量
METHOD方法声明
PARAMETER参数声明
CONSTRUCTOR构造函数声明
LOCAL_VARIABLE本地变量声明
ANNOTATION_TYPE注解类型声明
PACKAGE包声明
TYPE_PARAMETER类型参数声明JavaSE8引进可以应用于类的泛型声明之处
TYPE_USEJavaSE8引进此类型包括类型声明和类型参数声明
2.6. 获取注解信息
package com.gblfy.elk.annotate;import java.lang.annotation.*;/*** ElementType.TYPE 注解在类上生效* ElementType.METHOD 注解在方法上生效* ElementType.FIELD 注解在属性上生效* Retention 加此注解反射才可以获取* Inherited 子类可以继承*/
Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD,ElementType.ANNOTATION_TYPE})
Retention(RetentionPolicy.RUNTIME)
Inherited
public interface MayiktName {
}
package com.gblfy.elk.entity;import com.gblfy.elk.annotate.MayiktName;MayiktName
public class UserEntity {private String userName;private Integer userAge;MayiktNamepublic String publicName;public UserEntity() {System.out.println(执行无参构造函数);}public UserEntity(String userName, Integer userAge) {System.out.println(执行有参构造函数);this.userName userName;this.userAge userAge;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName userName;}public Integer getUserAge() {return userAge;}public void setUserAge(Integer userAge) {this.userAge userAge;}public String getPublicName() {return publicName;}public void setPublicName(String publicName) {this.publicName publicName;}Overridepublic String toString() {final StringBuffer sb new StringBuffer(UserEntity{);sb.append(userName).append(userName).append(\);sb.append(, userAge).append(userAge);sb.append(});return sb.toString();}MayiktNameprivate void mayikt() {System.out.println(mayikt);}MayiktNameprivate Integer sum(Integer a, Integer b) {return a b;}
}
/*** 注解联练习** author gblfy* date 2022-03-13*/
public class AnnotateCase {//判断某类上是否加上MayiktName注解Testpublic void classAnnotateTest() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException {//加载类Class? userClass Class.forName(com.gblfy.elk.entity.UserEntity);// 1.获取当前类上的注解MayiktName declaredAnnotation userClass.getDeclaredAnnotation(MayiktName.class);System.out.println(declaredAnnotation);}//判断指定方法上是否加上MayiktName注解Testpublic void methodAnnotateTest() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException {//加载类Class? userClass Class.forName(com.gblfy.elk.entity.UserEntity);//创建类实例Object o userClass.newInstance();//获取指定mayikt方法Method method userClass.getDeclaredMethod(mayikt);//获取该方法上的注解,有则返回无则返回nullMayiktName mayiktName method.getDeclaredAnnotation(MayiktName.class);System.out.println(mayiktName);}//判断某属性上是否加上MayiktName注解Testpublic void fieldAnnotateTest() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, NoSuchFieldException {//加载类Class? userClass Class.forName(com.gblfy.elk.entity.UserEntity);// 1.获取属性上的注解Field publicName userClass.getDeclaredField(publicName);MayiktName mayiktName publicName.getDeclaredAnnotation(MayiktName.class);System.out.println(mayiktName);}
}
2.7. 注解如何生效
实际项目中 注解想生效通过反射aop机制
2.8. 注解实现案例
自定义限流注解
对我们接口实现 限流 比如 每s 只能访问1次 或者每s 访问两次。 Maven dependencygroupIdcom.alibaba/groupIdartifactIdfastjson/artifactIdversion1.2.79/version/dependencydependencygroupIdcom.google.guava/groupIdartifactIdguava/artifactIdversion22.0/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId/dependencydependencygroupIdorg.apache.commons/groupIdartifactIdcommons-lang3/artifactIdversion3.12.0/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency使用谷歌的guava例子
package com.gblfy.elk.controller;import com.gblfy.elk.annotate.GblfyStreamLimit;
import com.google.common.util.concurrent.RateLimiter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;RestController
public class SreamLimitController {/*** 每秒生成1.0个令牌* 滑动窗口、令牌桶、漏桶算法实现*/private RateLimiter rateLimiter RateLimiter.create(1.0);GetMapping(/get)public String get() {System.out.println(-----------------执行目标方法-----------------);boolean result rateLimiter.tryAcquire();if (!result) {return 当前访问人数过多请稍后重试!;}return my is get;}GetMapping(/add)public String add() {return my is add;}
}
2.09. 封装自定义注解限流框架
整合自定义注解
package com.gblfy.elk.annotate;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 自定义请求限流注解** author gblfy* date 2022-03-13*/
Target(ElementType.METHOD)
Retention(RetentionPolicy.RUNTIME)
public interface GblfyStreamLimit {/*** 限流名称** return*/String name() default ;/*** 限流次数默认限流频次 1秒/20次** return*/double limitNum() default 20.0;
}
2.10. 整合Aop实现接口限流
package com.gblfy.elk.aop;import com.gblfy.elk.annotate.GblfyStreamLimit;
import com.google.common.util.concurrent.RateLimiter;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.util.concurrent.ConcurrentHashMap;Aspect
Component
public class StreamLimitAop {//并发map储存private ConcurrentHashMapString, RateLimiter rateLimiterStrategy new ConcurrentHashMap();/*** 只要在方法上添加该自定义限流注解就会被AOP环绕通知拦截** param joinPoint* return*/Around(value annotation(com.gblfy.elk.annotate.GblfyStreamLimit))public Object around(ProceedingJoinPoint joinPoint) {try {//获取拦截的方法名Signature sig joinPoint.getSignature();//获取拦截的方法名MethodSignature methodSignature (MethodSignature) sig;// 判断方法上是否有加上该注解如果有加上注解则限流GblfyStreamLimit gblfyStreamLimit methodSignature.getMethod().getDeclaredAnnotation(GblfyStreamLimit.class);if (gblfyStreamLimit null) {// 执行目标方法return joinPoint.proceed();}// 1.获取注解上的限流名称(name)String name gblfyStreamLimit.name();// 2.获取注解上的limitNum(限流次数)实现对不同的方法限流策略不一样的效果double limitNum gblfyStreamLimit.limitNum();RateLimiter rateLimiter rateLimiterStrategy.get(name);if (rateLimiter null) {//3.动态匹配并创建不同的限流策略rateLimiter RateLimiter.create(limitNum);rateLimiterStrategy.put(name, rateLimiter);}// 开始限流boolean result rateLimiter.tryAcquire();if (!result) {return 当前访问人数过多请稍后重试!;}return joinPoint.proceed();} catch (Throwable throwable) {return 系统出现了错误!;}}/*** 前置通知*/Before(value annotation(com.gblfy.elk.annotate.GblfyStreamLimit))public void before() {System.out.println(----------------------前置通知----------------------);}/*** 后置通知*/AfterReturning(value annotation(com.gblfy.elk.annotate.GblfyStreamLimit))public void AfterReturning() {System.out.println(----------------------后置通知----------------------);}/*** 异常通知** param point*/AfterThrowing(value annotation(com.gblfy.elk.annotate.GblfyStreamLimit), throwing e)public void serviceAspect(JoinPoint point, Exception e) {System.out.println(----------------------异常通知----------------------);}
}
2.11. 案例
package com.gblfy.elk.controller;import com.gblfy.elk.annotate.GblfyStreamLimit;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;RestController
public class SreamLimitController {GetMapping(/get2)GblfyStreamLimit(name get2, limitNum 1.0)public String get2() {System.out.println(-----------------执行目标方法-----------------);return my is get;}GetMapping(/add)public String add() {return my is add;}
}
http://127.0.0.1:8080/get http://127.0.0.1:8080/my