网站做实名验证如何优化

web/2025/9/30 4:42:56/文章来源:
网站做实名验证,如何优化,导航网站 win8风格,wordpress 4.7 模板世界上只有一种英雄主义#xff0c;就是看清生活的真相之后依然热爱生活。对于 Lombok 我相信大部分人都不陌生#xff0c;但对于它的实现原理以及缺点却鲜为人知#xff0c;而本文将会从 Lombok 的原理出发#xff0c;手撸一个简易版的 Lombok#xff0c;让你理解这个热门… 世界上只有一种英雄主义就是看清生活的真相之后依然热爱生活。对于 Lombok 我相信大部分人都不陌生但对于它的实现原理以及缺点却鲜为人知而本文将会从 Lombok 的原理出发手撸一个简易版的 Lombok让你理解这个热门技术背后的执行原理以及它的优缺点。简介 在讲原理之前我们先来复习一下 Lombok (老司机可直接跳过本段)。Lombok 是一个非常热门的开源项目 (https://github.com/rzwitserloot/lombok)使用它可以有效的解决 Java 工程中那些繁琐又重复代码例如 Setter、Getter、toString、equals、hashCode 以及非空判断等都可以使用 Lombok 有效的解决。使用 1.添加 Lombok 插件在 IDE 中必须安装 Lombok 插件才能正常调用被 Lombok 修饰的代码以 Idea 为例添加的步骤如下点击 File Settings Plugins 进入插件管理页面点击 Browse repositories...搜索 Lombok Plugin点击 Install plugin 安装插件重启 IntelliJ IDEA安装完成如下图所示2.添加 Lombok 库接下来我们需要在项目中添加最新的 Lombok 库如果是 Maven 项目直接在 pom.xml 中添加如下配置dependencies!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.12/versionscopeprovided/scope/dependency /dependencies 如果是 JDK 9 可使用模块的方式添加配置如下annotationProcessorPathspathgroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.12/version/path /annotationProcessorPaths 3.使用 Lombok接下来到了前半部分中最重要的 Lombok 使用环节了我们先来看在没有使用 Lombok 之前的代码public class Person {private Integer id;private String name;public Integer getId() {return id;}public void setId(Integer id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;} } 这是使用 Lombok 之后的代码Getter Setter public class Person {private Integer id;private String name; } 可以看出在 Lombok 之后用一个注解就搞定了之前所有 Getter/Setter 的代码让代码瞬间优雅了很多。Lombok 所有注解如下val用在局部变量前面相当于将变量声明为 finalNonNull给方法参数增加这个注解会自动在方法内对该参数进行是否为空的校验如果为空则抛出 NPENullPointerExceptionCleanup自动管理资源用在局部变量之前在当前变量范围内即将执行完毕退出之前会自动清理资源自动生成 try-finally 这样的代码来关闭流Getter/Setter用在属性上再也不用自己手写 setter 和 getter 方法了还可以指定访问范围ToString用在类上可以自动覆写 toString 方法当然还可以加其他参数例如 ToString(exclude”id”) 排除 id 属性或者 ToString(callSupertrue, includeFieldNamestrue) 调用父类的 toString 方法包含所有属性EqualsAndHashCode用在类上自动生成 equals 方法和 hashCode 方法NoArgsConstructor, RequiredArgsConstructor and AllArgsConstructor用在类上自动生成无参构造和使用所有参数的构造函数以及把所有 NonNull 属性作为参数的构造函数如果指定 staticNameof 参数同时还会生成一个返回类对象的静态工厂方法比使用构造函数方便很多Data注解在类上相当于同时使用了 ToString、EqualsAndHashCode、Getter、Setter 和 RequiredArgsConstrutor 这些注解对于 POJO 类十分有用Value用在类上是 Data 的不可变形式相当于为属性添加 final 声明只提供 getter 方法而不提供 setter 方法Builder用在类、构造器、方法上为你提供复杂的 builder APIs让你可以像如下方式一样调用Person.builder().name(xxx).city(xxx).build()SneakyThrows自动抛受检异常而无需显式在方法上使用 throws 语句Synchronized用在方法上将方法声明为同步的并自动加锁而锁对象是一个私有的属性 或LOCK而 Java 中的 synchronized 关键字锁对象是 this锁在 this 或者自己的类对象上存在副作用就是你不能阻止非受控代码去锁 this 或者类对象这可能会导致竞争条件或者其它线程错误Getter(lazytrue)可以替代经典的 Double Check Lock 样板代码Log根据不同的注解生成不同类型的 log 对象但是实例名称都是 log有六种可选实现类CommonsLog Creates log org.apache.commons.logging.LogFactory.getLog(LogExample.class);Log Creates log java.util.logging.Logger.getLogger(LogExample.class.getName());Log4j Creates log org.apache.log4j.Logger.getLogger(LogExample.class);Log4j2 Creates log org.apache.logging.log4j.LogManager.getLogger(LogExample.class);Slf4j Creates log org.slf4j.LoggerFactory.getLogger(LogExample.class);XSlf4j Creates log org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);它们的具体使用如下① val 使用val sets new HashSetString(); // 相当于 final SetString sets new HashSet(); ② NonNull 使用public void notNullExample(NonNull String string) {string.length(); } // 相当于 public void notNullExample(String string) {if (string ! null) {string.length();} else {throw new NullPointerException(null);} } ③ Cleanup 使用public static void main(String[] args) {try {Cleanup InputStream inputStream new FileInputStream(args[0]);} catch (FileNotFoundException e) {e.printStackTrace();}// 相当于InputStream inputStream null;try {inputStream new FileInputStream(args[0]);} catch (FileNotFoundException e) {e.printStackTrace();} finally {if (inputStream ! null) {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}} } ④ Getter/Setter 使用Setter(AccessLevel.PUBLIC) Getter(AccessLevel.PROTECTED) private int id; private String shap; ⑤ ToString 使用ToString(exclude id, callSuper true, includeFieldNames true) public class LombokDemo {private int id;private String name;private int age;public static void main(String[] args) {// 输出 LombokDemo(superLombokDemo48524010, namenull, age0)System.out.println(new LombokDemo());} } ⑥ EqualsAndHashCode 使用EqualsAndHashCode(exclude {id, shape}, callSuper false) public class LombokDemo {private int id;private String shap; } ⑦ NoArgsConstructor、RequiredArgsConstructor、AllArgsConstructor 使用NoArgsConstructor RequiredArgsConstructor(staticName of) AllArgsConstructor public class LombokDemo {NonNullprivate int id;NonNullprivate String shap;private int age;public static void main(String[] args) {new LombokDemo(1, Java);// 使用静态工厂方法LombokDemo.of(2, Java);// 无参构造new LombokDemo();// 包含所有参数new LombokDemo(1, Java, 2);} } ⑧ Builder 使用Builder public class BuilderExample {private String name;private int age;Singularprivate SetString occupations;public static void main(String[] args) {BuilderExample test BuilderExample.builder().age(11).name(Java).build();} } ⑨ SneakyThrows 使用public class ThrowsTest {SneakyThrows()public void read() {InputStream inputStream new FileInputStream();}SneakyThrowspublic void write() {throw new UnsupportedEncodingException();}// 相当于public void read() throws FileNotFoundException {InputStream inputStream new FileInputStream();}public void write() throws UnsupportedEncodingException {throw new UnsupportedEncodingException();} } ⑩ Synchronized 使用public class SynchronizedDemo {Synchronizedpublic static void hello() {System.out.println(world);}// 相当于private static final Object $LOCK new Object[0];public static void hello() {synchronized ($LOCK) {System.out.println(world);}} } ⑪ Getter(lazy true) 使用public class GetterLazyExample {Getter(lazy true)private final double[] cached expensive();private double[] expensive() {double[] result new double[1000000];for (int i 0; i result.length; i) {result[i] Math.asin(i);}return result;} } // 相当于 import java.util.concurrent.atomic.AtomicReference; public class GetterLazyExample {private final AtomicReferencejava.lang.Object cached new AtomicReference();public double[] getCached() {java.lang.Object value this.cached.get();if (value null) {synchronized (this.cached) {value this.cached.get();if (value null) {final double[] actualValue expensive();value actualValue null ? this.cached : actualValue;this.cached.set(value);}}}return (double[]) (value this.cached ? null : value);}private double[] expensive() {double[] result new double[1000000];for (int i 0; i result.length; i) {result[i] Math.asin(i);}return result;} } 原理分析 我们知道 Java 的编译过程大致可以分为三个阶段解析与填充符号表注解处理分析与字节码生成编译过程如下图所示而 Lombok 正是利用「注解处理」这一步进行实现的Lombok 使用的是 JDK 6 实现的 JSR 269: Pluggable Annotation Processing API (编译期的注解处理器) 它是在编译期时把 Lombok 的注解代码转换为常规的 Java 方法而实现优雅地编程的。这一点可以在程序中得到验证比如本文刚开始用 Data 实现的代码在我们编译之后查看 Person 类的编译源码发现代码竟然是这样的可以看出 Person 类在编译期被注解翻译器修改成了常规的 Java 方法添加 Getter、Setter、equals、hashCode 等方法。Lombok 的执行流程如下可以看出在编译期阶段当 Java 源码被抽象成语法树 (AST) 之后Lombok 会根据自己的注解处理器动态的修改 AST增加新的代码 (节点)在这一切执行之后再通过分析生成了最终的字节码 (.class) 文件这就是 Lombok 的执行原理。手撸一个 Lombok 我们实现一个简易版的 Lombok 自定义一个 Getter 方法我们的实现步骤是自定义一个注解标签接口并实现一个自定义的注解处理器利用 tools.jar 的 javac api 处理 AST (抽象语法树)使用自定义的注解处理器编译代码。这样就可以实现一个简易版的 Lombok 了。1.定义自定义注解和注解处理器首先创建一个 MyGetter.java 自定义一个注解代码如下import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;Retention(RetentionPolicy.SOURCE) // 注解只在源码中保留 Target(ElementType.TYPE) // 用于修饰类 public interface MyGetter { // 定义 Getter} 再实现一个自定义的注解处理器代码如下import com.sun.source.tree.Tree; import com.sun.tools.javac.api.JavacTrees; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.processing.JavacProcessingEnvironment; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.TreeTranslator; import com.sun.tools.javac.util.*;import javax.annotation.processing.*; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; import java.util.Set;SupportedSourceVersion(SourceVersion.RELEASE_8) SupportedAnnotationTypes(com.example.lombok.MyGetter) public class MyGetterProcessor extends AbstractProcessor {private Messager messager; // 编译时期输入日志的private JavacTrees javacTrees; // 提供了待处理的抽象语法树private TreeMaker treeMaker; // 封装了创建AST节点的一些方法private Names names; // 提供了创建标识符的方法Overridepublic synchronized void init(ProcessingEnvironment processingEnv) {super.init(processingEnv);this.messager processingEnv.getMessager();this.javacTrees JavacTrees.instance(processingEnv);Context context ((JavacProcessingEnvironment) processingEnv).getContext();this.treeMaker TreeMaker.instance(context);this.names Names.instance(context);}Overridepublic boolean process(Set? extends TypeElement annotations, RoundEnvironment roundEnv) {Set? extends Element elementsAnnotatedWith roundEnv.getElementsAnnotatedWith(MyGetter.class);elementsAnnotatedWith.forEach(e - {JCTree tree javacTrees.getTree(e);tree.accept(new TreeTranslator() {Overridepublic void visitClassDef(JCTree.JCClassDecl jcClassDecl) {ListJCTree.JCVariableDecl jcVariableDeclList List.nil();// 在抽象树中找出所有的变量for (JCTree jcTree : jcClassDecl.defs) {if (jcTree.getKind().equals(Tree.Kind.VARIABLE)) {JCTree.JCVariableDecl jcVariableDecl (JCTree.JCVariableDecl) jcTree;jcVariableDeclList jcVariableDeclList.append(jcVariableDecl);}}// 对于变量进行生成方法的操作jcVariableDeclList.forEach(jcVariableDecl - {messager.printMessage(Diagnostic.Kind.NOTE, jcVariableDecl.getName() has been processed);jcClassDecl.defs jcClassDecl.defs.prepend(makeGetterMethodDecl(jcVariableDecl));});super.visitClassDef(jcClassDecl);}});});return true;}private JCTree.JCMethodDecl makeGetterMethodDecl(JCTree.JCVariableDecl jcVariableDecl) {ListBufferJCTree.JCStatement statements new ListBuffer();// 生成表达式 例如 this.a a;JCTree.JCExpressionStatement aThis makeAssignment(treeMaker.Select(treeMaker.Ident(names.fromString(this)), jcVariableDecl.getName()), treeMaker.Ident(jcVariableDecl.getName()));statements.append(aThis);JCTree.JCBlock block treeMaker.Block(0, statements.toList());// 生成入参JCTree.JCVariableDecl param treeMaker.VarDef(treeMaker.Modifiers(Flags.PARAMETER),jcVariableDecl.getName(), jcVariableDecl.vartype, null);ListJCTree.JCVariableDecl parameters List.of(param);// 生成返回对象JCTree.JCExpression methodType treeMaker.Type(new Type.JCVoidType());return treeMaker.MethodDef(treeMaker.Modifiers(Flags.PUBLIC),getNewMethodName(jcVariableDecl.getName()), methodType, List.nil(),parameters, List.nil(), block, null);}private Name getNewMethodName(Name name) {String s name.toString();return names.fromString(get s.substring(0, 1).toUpperCase() s.substring(1, name.length()));}private JCTree.JCExpressionStatement makeAssignment(JCTree.JCExpression lhs, JCTree.JCExpression rhs) {return treeMaker.Exec(treeMaker.Assign(lhs,rhs));} } 自定义的注解处理器是我们实现简易版的 Lombok 的重中之重我们需要继承 AbstractProcessor 类重写它的 init() 和 process() 方法在 process() 方法中我们先查询所有的变量在给变量添加对应的方法。我们使用 TreeMaker 对象和 Names 来处理 AST如上代码所示。当这些代码写好之后我们就可以新增一个 Person 类来试一下我们自定义的 MyGetter 功能了代码如下MyGetter public class Person {private String name; } 2.使用自定义的注解处理器编译代码上面的所有流程执行完成之后我们就可以编译代码测试效果了。首先我们先进入代码的根目录执行以下三条命令。进入的根目录如下① 使用 tools.jar 编译自定义的注解器javac -cp $JAVA_HOME/lib/tools.jar MyGetter* -d .注意命令最后面有一个“.”表示当前文件夹。② 使用自定义注解器编译 Person 类javac -processor com.example.lombok.MyGetterProcessor Person.java③ 查看 Person 源码javap -p Person.class源码文件如下可以看到我们自定义的 getName() 方法已经成功生成了到这里简易版的 Lombok 就大功告成了。Lombok 优缺点 Lombok 的优点很明显它可以让我们写更少的代码节约了开发时间并且让代码看起来更优雅它的缺点有以下几个。缺点1降低了可调试性Lombok 会帮我们自动生成很多代码但这些代码是在编译期生成的因此在开发和调试阶段这些代码可能是“丢失的”这就给调试代码带来了很大的不便。缺点2可能会有兼容性问题Lombok 对于代码有很强的侵入性加上现在 JDK 版本升级比较快每半年发布一个版本而 Lombok 又属于第三方项目并且由开源团队维护因此就没有办法保证版本的兼容性和迭代的速度进而可能会产生版本不兼容的情况。缺点3可能会坑到队友尤其对于组人来的新人可能影响更大假如这个之前没用过 Lombok当他把代码拉下来之后因为没有安装 Lombok 的插件在编译项目时就会提示找不到方法等错误信息导致项目编译失败进而影响了团结成员之间的协作。缺点4破坏了封装性面向对象封装的定义是通过访问权限控制隐藏内部数据外部仅能通过类提供的有限的接口访问和修改内部数据。也就是说我们不应该无脑的使用 Lombok 对外暴露所有字段的 Getter/Setter 方法因为有些字段在某些情况下是不允许直接修改的比如购物车中的商品数量它直接影响了购物详情和总价因此在修改的时候应该提供统一的方法进行关联修改而不是给每个字段添加访问和修改的方法。小结 本文我们介绍了 Lombok 的使用以及执行原理它是通过 JDK 6 实现的 JSR 269: Pluggable Annotation Processing API (编译期的注解处理器) 在编译期时把 Lombok 的注解转换为 Java 的常规方法的我们可以通过继承 AbstractProcessor 类重写它的 init() 和  process() 方法实现一个简易版的 Lombok。但同时 Lombok 也存在这一些使用上的缺点比如降低了可调试性、可能会有兼容性等问题因此我们在使用时要根据自己的业务场景和实际情况来选择要不要使用 Lombok以及应该如何使用 Lombok。最后提醒一句再好的技术也不是万金油就好像再好的鞋子也得适合自己的脚才行感谢阅读希望本文对你能所启发。觉得不错的话分享给需要的朋友谢谢。参考 鸣谢https://juejin.im/post/5a6eceb8f265da3e467555fehttps://www.tuicool.com/articles/y6rUz2V【END】《大厂内部资料》Redis 性能优化的 13 条军规全网首发因为我说volatile 是轻量级的 synchronized面试官让我回去等通知Java14发布Switch竟如此简单Lombok也不需要了来用Idea搭建Java14吧关注下方二维码订阅更多精彩内容朕已阅

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

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

相关文章

兰州城市建设学校网上报名网站商务网站开发公司

C程序设计 (第四版) 谭浩强 例10.1 例10.1 从键盘输入一些字符,逐个把它们送到磁盘上去,直到用户输入一个“#”为止。 IDE工具:VS2010 Note: 使用不同的IDE工具可能有部分差异。 代码块 方法:使用指针&…

汽车网站开发方案郑州专业做网站企业

首先我们在new 一个对象的时候,对象的id是唯一确定的;将对象add入list中时,放入list中的其实是对象的引用 ;而每次循环只是简单的set 对象的属性,set新的属性值,而add进list中的对象还是同一个对象id&#…

建筑招工网站虚拟机安装 wordpress

档案数字化管理提供了便捷、高效和安全的档案管理服务,帮助组织更好地管理和利用自己的档案资源。 具体来说,专久智能档案数字化管理可以提供以下服务: 1. 档案扫描和数字化:将纸质档案通过扫描仪转换为数字格式,包括文…

若比邻跨境电商网站资阳自贡网站建设平台

目录 安装Pyecharts 安装对应的地图拓展: 准备数据 使用 pyecharts 模块中的 Geo 函数: 使用 pyecharts 模块中的 map 函数: 把一些地域性比较明显的数据显示在一张地图上,远比给别人一个 Excel 文件好得多。 Matplotlib 中…

网站建设app开发学习线上营销活动主要有哪些

目录如何实现一个服务器C编写程序配置CMakeLists.txt编译并运行python创建并编写脚本运行平台:华硕 Thinker Edge R 瑞芯微 RK3399Pro 固件版本:Tinker_Edge_R-Debian-Stretch-V1.0.4-20200615 记录自【古月居】古月ROS入门21讲 | 一学就会的ROS机器人入…

大型网站服务器配置荣耀手机商城官方网站售后

背景描述 我们在调用OpenAI的接口时,有些内容可能是违反条例的,所以官方提供了一个工具来检测。 安装依赖 pip install --upgrade --quiet langchain-core langchain langchain-openai编写代码 下文中我们使用了: OpenAIModerationChain 这个工具来…

龙岗在线网站建设怎么做品牌推广网站

页面可见性 页面可见性介绍 长期以来我们一直缺少一个判断用户是否正在浏览某个指定标签页的方法。用户是否去看别的网站了?他们切换回来了吗?现在html5里页面可见性接口就提供给了程序员一个方法,让他们使用visibilitychange页面事件来判断…

汽车网站建设公司wordpress后台轮播图设置

导读在Red Hat宣布将限制AlmaLinuxOS或Rocky Linux等社区发行版对其公共仓库的访问后,最近Red Hat与IBM之间发生了一些争论,有鉴于此,SUSE今天宣布计划为RHEL和CentOS用户提供一个免费的替代方案。 SUSE已经开发了SUSE Linux Enterprise (SLE…

建一个网站怎么赚钱网站建设与运营的市场

文|新熔财经 作者|宏一 自2019年4月《电动自行车安全技术规范》发布至今,电动车的新国标标准已经实施5年,市场上的争议也此起彼伏地持续了5年。 因为新国标对电动车的各项技术标准提出的明确要求,其中,最…

即墨网站开发2345网址大全首页

来源:Prophet2019年,战略数字化转型的重要性已经不止于IT领域,而影响着全公司的竞争力。企业的相关预算直线攀升,利益相关方所关注的颠覆性技术数量急剧增加。数字化项目开始由首席高管主导,并由相互协作的跨职能团队管…

建设一个网站首先需要什么问题微信小程序如何推广

组网需求 用户希望以PPPoE拨号方式接入广域网,如图1所示,Router作为PPPoE客户端,得到PPPoE服务器的认证后获得IP地址,实现用户接入互联网的需求。内网网关地址(即VLANIF1接口的IP地址)为10.137.32.1/24。 …

域名注册网站排行一流的上海网站建设公司

问题:如图,1部分的表头是动态的根据日期变化,2部分是数据库对应的字段,静态不变的; 解决方案:如果不看1的部分,2部分内容可以根据实体类注解的方式导出,那么我们是不是可以先将动态表…

中关村网站建设公司wordpress微商授权

目前,国外已有较多有关零信任网络的研究与实践,包括谷歌的 BeyondCorp、BeyondProd,软件定义边界(Software Defined Perimeter,SDP) 及盖特提出的“持续自适应风险与信任评估”等。国内也有不少安全厂商积极…

中国flash网站模板中心优秀建筑方案设计文本

基于C语言的凸包算法实现非计算机专业,代码有些的不好的地方,大佬轻喷^ _ ^根据要求,需要使用C语言实现凸包算法——Graham扫描法,本文将从算法理解、实现思路、遇到的问题及其解决方案三个方面来阐述实现过程。算法理解凸包算法G…

做淘宝那样的网站要多少钱商业网站建设规划范文

现代企业离不开数据,而数据的分析与应用更是成为企业走向成功的关键之一。然而,随着数据量的不断增长,传统的数据分析方法已经无法满足企业的需求。这时,智能数据分析系统应运而生,成为企业决策的得力助手。那么&#…

苏州建设网站市政中标项目手机网站怎么搭建

时间模块 UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时间。在中国为UTC8。DST(Daylight Saving Time)即夏令时。 在Python中,通常有这几种方式来表示时间:1&…

职业生涯规划网站开发背景新东方教育培训机构

一、数值类型1,int 类型 4字节 。备注:一个字节8位,即有32位,存在一个符号位。所以能存的数值大小为-2的31次方到2的31次方;2,tinyint 类型 1字节。3,smallint 类型 2字节4,medi…

网站开发 图片存放网站建设流程六个步骤

背景在使用PyTorch深度学习框架的时候,不管是训练还是测试,代码中引入PyTorch的第一句总是:import torch在Gemfield前述专栏文章里,我们已经得知,torch/csrc/stub.cpp链接libshm.so、libtorch_python.so、libcaffe2_gp…

网站开发需要20万网站后台登陆地址

小蓝有一个超大的仓库,可以摆放很多货物。 现在,小蓝有 n 箱货物要摆放在仓库,每箱货物都是规则的正方体。小蓝规定了长、宽、高三个互相垂直的方向,每箱货物的边都必须严格平行于长、宽、高。 小蓝希望所有的货物最终摆成一个大…