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

SSM学习——Spring AOP与AspectJ

Spring AOP与AspectJ

概念

AOP的全称为Aspect-Oriented Programming,即面向切面编程。

想象你是汉堡店的厨师,每一份汉堡都有好几层,这每一层都可以视作一个切面。现在有一位顾客想要品尝到不同风味肉馅的汉堡,如果按照传统的方式,你需要做多个汉堡,每个汉堡只有肉馅是不一样的,但是你每做一个汉堡都要重新制作面包。而聪明的厨师只需做一个汉堡,仅将肉饼那一层分成不同口味的几个区域,这样你就不需要再重复制作面包了。

对于程序员也是一样的,有多少个接口就要写或复制多少代码那一定是无法忍受的,我们只想关心不同的那部分。

尽管想通俗来讲,但是还是要去熟悉专业的概念:

  • Aspect:切面,类似于Java类声明,里面会有PointcutAdvice
  • Joint point:连接点,在程序执行过程中某个阶段点
  • Pointcut:切入点,切面与程序流的交叉点,往往此处需要处理
  • Advice:通知或增强,在切入点处所要执行的代码。可以理解为切面类中的方法。
  • Target object:目标对象,指所有被通知的对象。
  • Proxy:代理,将通知应用到目标对象后,被动态创建的对象。
  • Weaving:织入,将切面代码插到目标对象上,从而生成代理对象的过程。

别担心,我们之后会通过代码来慢慢理解。

AOP的实现

AOP的实现主要分为静态代理动态代理,在本教程中静态代理我们用AspectJ,而动态代理用Spring AOP

静态代理在编译期就确定了代理类,而动态代理需要靠反射机制动态生成代理类。

Spring AOP动态代理有两种实现方式:一种是JDK动态代理,这种方式需要接口;另一种是CGLib动态代理,这种方式不依赖接口。

有了以上的知识,我们开始写代码,首先新创建一个Maven项目top.cairbin.test2,如果你不会请回去看之前的章节。

然后在pom.xml<dependencies></dependencies>之间添加依赖包

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.16</version>
</dependency>		
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>		
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version>
</dependency>

我们去实现一个IUser接口,要求接口内有两个方法void addUser()void deleteUser()

package top.cairbin.test2;public interface IUser {void addUser();void deleteUser();
}

接下来定义一个实现该接口的User

package top.cairbin.test2;public class User implements IUser{@Overridepublic void addUser() {System.out.println("进行增加用户操作!");}@Overridepublic void deleteUser() {System.out.println("进行删除用户操作!");}
}

我们定义一个切面类,该类中的两个方法void check()void log()分别模拟权限检查和日志记录功能。

切面类如下所示

package top.cairbin.test2;public class MyAspect {public void check() {System.out.println("正在模拟权限认证");}public void log() {System.out.println("正在模拟日志记录");}
}

JDK动态代理

接下来创建代理类JdkProxy,这个类实现了JDK动态代理的InvocationHandler接口,并实现代理方法。

package top.cairbin.test2;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class JdkProxy implements InvocationHandler{private final IUser user;public JdkProxy(IUser user) {this.user = user;}public static Object createProxy(IUser user) {ClassLoader classLoader = JdkProxy.class.getClassLoader();// 被代理对象实现的所有接口Class[] clazz = user.getClass().getInterfaces();// 使用代理类,进行增强,返回的是代理后的对象return  Proxy.newProxyInstance(classLoader,clazz,new JdkProxy(user));}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 声明切面MyAspect myAspect = new MyAspect();// 前增强myAspect.check();// 在目标类上调用方法,并传入参数Object obj = method.invoke(user, args);// 后增强myAspect.log();return obj;}}

然后尝试在App.javamain方法中使用它们

package top.cairbin.test2;public class App 
{public static void main( String[] args ){// 创建目标对象IUser user= new User();// 创建代理,并从代理中获取增强后的目标对象IUser user2 = (IUser)JdkProxy.createProxy(user);// 执行方法user2.addUser();user2.deleteUser();}
}

输出结果如下图所示

CGLib动态代理

我们不妨尝试使用CGLib来玩一下

创建一个新的类,名称为CglibProxy,并实现接口MethodInterceptor以及相应的方法

package top.cairbin.test2;import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;public class CglibProxy implements MethodInterceptor {public static Object createProxy(Object target){Enhancer enhancer = new Enhancer();  enhancer.setSuperclass(target.getClass());  enhancer.setCallback(new CglibProxy()); return enhancer.create();}@Overridepublic Object intercept(Object obj, Method method, 	Object[] args, MethodProxy proxy) throws Throwable {// 声明切面MyAspect myAspect = new MyAspect();// 前增强myAspect.check();//获取增强后的目标对象Object target = proxy.invokeSuper(obj, args);// 后增强myAspect.log();return target;}
}

尝试调用下

package top.cairbin.test2;public class App 
{public static void main( String[] args ){IUser user = (IUser)CglibProxy.createProxy (new User());user.addUser();user.deleteUser();}
}

不出所料,果然成功了

我们仔细观察CGLib的这几段代码,在CglibProxy类中我们并没有用到IUser这个接口,而是返回Object,然后外面也就是调用者那里强制转换为IUser类型!

不妨再“懒”一些,我们借助Spring的依赖注入,从Spring的容器中直接返回增强后的实现了IUser接口的对象试一试。

首先在resources/AppCtx.xml中编写Bean的配置(这里有坑,如果行不通回前面的文章看看)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"><!-- 目标类 --><bean id="user" class="top.cairbin.test2.User" /><!-- 切面类 --><bean id="myAspect" class="top.cairbin.test2.MyAspect" /><!-- 使用Spring代理工厂定义一个名称为userProxy的代理对象 --><bean id="userProxy" class="org.springframework.aop.framework.ProxyFactoryBean"><!-- 指定代理实现的接口--><property name="proxyInterfaces" value="top.cairbin.test2.IUser" /><!-- 指定目标对象 --><property name="target" ref="user" /><!-- 指定切面,织入环绕通知 --><property name="interceptorNames" value="myAspect" /><!-- 指定代理方式,true:使用cglib,false(默认):使用jdk动态代理 --><property name="proxyTargetClass" value="true" /></bean>
</beans>

修改下MyAspect类,并实现接口MethodInterceptor

package top.cairbin.test2;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;public class MyAspect implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {this.check();// 执行目标方法Object obj = mi.proceed();this.log();return obj;}public void check() {System.out.println("正在模拟权限认证");}public void log() {System.out.println("正在模拟日志记录");}
}

App类中的main方法调用如下

package top.cairbin.test2;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App 
{public static void main( String[] args ){ApplicationContext app = new ClassPathXmlApplicationContext("AppCtx.xml");IUser user = (IUser)app.getBean("userProxy");user.addUser();user.deleteUser();}
}

点击运行得到结果

AspectJ静态代理

使用AspectJ静态代理,我们重新设计下MyAspect切面类

package top.cairbin.test2;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/*** 切面类,在此类中编写通知*/
@Aspect
@Component
public class MyAspect {// 定义切入点表达式@Pointcut("execution(* top.cairbin.test2.*.*(..))")// 使用一个返回值为void、方法体为空的方法来命名切入点private void myPointCut(){}// 前置通知@Before("myPointCut()")public void myBefore(JoinPoint joinPoint) {System.out.print("前置通知 :模拟执行权限检查...,");System.out.print("目标类是:"+joinPoint.getTarget() );System.out.println(",被织入增强处理的目标方法为:"+joinPoint.getSignature().getName());}// 后置通知@AfterReturning(value="myPointCut()")public void myAfterReturning(JoinPoint joinPoint) {System.out.print("后置通知:模拟记录日志...," );System.out.println("被织入增强处理的目标方法为:"+ joinPoint.getSignature().getName());}// 环绕通知	@Around("myPointCut()")public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {// 开始System.out.println("环绕开始:执行目标方法之前,模拟开启事务...");// 执行当前目标方法Object obj = proceedingJoinPoint.proceed();// 结束System.out.println("环绕结束:执行目标方法之后,模拟关闭事务...");return obj;}// 异常通知@AfterThrowing(value="myPointCut()",throwing="e")public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {System.out.println("异常通知:" + "出错了" + e.getMessage());}// 最终通知@After("myPointCut()")public void myAfter() {System.out.println("最终通知:模拟方法结束后的释放资源...");}
}

对于切入点注解@Pointcut("execution(* top.cairbin.test2.*.*(..))")表示对top.cairbin.test2这个包下的所有类的所有方法生效。

我们再来看看Spring中的Advice的几种类型:

  • org.springframework.aop.MethodBeforeAdvice,前置通知,目标方法执行前实施,可用于权限管理。
  • org.springframework.aop.AfterReturningAdvice,后置通知,在目标方法执行后实施,用于关闭文件流、上传文件、删除临时文件等。
  • org.aopalliance.intercept.MethodInterceptor,环绕通知,在目标方法实施前后,一般用于日志或事务管理。
  • org.springframework.aop.ThrowsAdvice,异常抛出通知,在抛出异常后实施。
  • org.springframework.aop.IntroductionInterceptor,引介通知,在目标类中添加新方法和属性,可以应用于修改老版本程序。

我们还要实现自动扫描和依赖注入,看看我们的User

package top.cairbin.test2;
import org.springframework.stereotype.Component;@Component
public class User implements IUser{@Overridepublic void addUser() {System.out.println("进行增加用户操作!");}@Overridepublic void deleteUser() {System.out.println("进行删除用户操作!");}
}

自然也少不了AppCtx.xml的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"><!-- 指定需要扫描的包,使注解生效 --><context:component-scan base-package="top.cairbin.test2" /><!-- 启动基于注解的声明式AspectJ支持 --><aop:aspectj-autoproxy />
</beans>

main方法中测试下,为了清楚,我这里仅调用了addUser一个方法

package top.cairbin.test2;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App 
{public static void main( String[] args ){ApplicationContext app = new ClassPathXmlApplicationContext("AppCtx.xml");IUser user = (IUser)app.getBean("user");user.addUser();}
}

我们发现当环绕通知与前置通知和后置通知同时使用的时候,优先级如下:

  • 环绕通知开始
  • 前置通知
  • 方法执行
  • 后置通知
  • 环绕通知结束

想必到了这里,你对AspectJ的使用有了一定的了解,但是对于相应的注解还是不太清楚,请仔细阅读下方图片中的表格,结合一开始的术语体会下:

相关文章:

SSM学习——Spring AOP与AspectJ

Spring AOP与AspectJ 概念 AOP的全称为Aspect-Oriented Programming&#xff0c;即面向切面编程。 想象你是汉堡店的厨师&#xff0c;每一份汉堡都有好几层&#xff0c;这每一层都可以视作一个切面。现在有一位顾客想要品尝到不同风味肉馅的汉堡&#xff0c;如果按照传统的方…...

Android 使用LeakCanary检测内存泄漏,分析原因

内存泄漏是指无用对象&#xff08;不再使用的对象&#xff09;持续占有内存或无用对象的内存得不到及时释放&#xff0c;从而造成内存空间的浪费称为内存泄漏。 平时我们在使用app时&#xff0c;少量的内存泄漏我们是发现不了的&#xff0c;但是当内存泄漏达到一定数量时&…...

Linux部署Kafka2.8.1

安装Jdk 首先确保你的机器上安装了Jdk&#xff0c;Kafka需要Java运行环境&#xff0c;低版本的Kafka还需要Zookeeper&#xff0c;我此次要安装的Kafka版本为2.8.1&#xff0c;已经内置了一个Zookeeper环境&#xff0c;所以我们可以不部署Zookeeper直接使用。 1、解压Jdk包 t…...

【pytest、playwright】allure报告生成视频和图片

目录 1、修改插件pytest_playwright 2、conftest.py配置 3、修改pytest.ini文件 4、运行case 5、注意事项 1、修改插件pytest_playwright pytest_playwright.py内容如下&#xff1a; # Copyright (c) Microsoft Corporation. # # Licensed under the Apache License, Ver…...

浅谈iOS开发中的自动引用计数ARC

1.ARC是什么 我们知道&#xff0c;在C语言中&#xff0c;创建对象时必须手动分配和释放适量的内存。然而&#xff0c;在 Swift 中&#xff0c;当不再需要类实例时&#xff0c;ARC 会自动释放这些实例的内存。 Swift 使用 ARC 来跟踪和管理应用程序的内存&#xff0c;其主要是由…...

Spring IoCDI(2)

IoC详解 通过上面的案例, 我们已经知道了IoC和DI的基本操作, 接下来我们来系统地学习Spring IoC和DI的操作. 前面我们提到的IoC控制反转, 就是将对象的控制权交给Spring的IoC容器, 由IoC容器创建及管理对象. (也就是Bean的存储). Bean的存储 我们之前只讲到了Component注解…...

30. UE5 RPG GamplayAbility的配置项

在上一篇文章&#xff0c;我们介绍了如何将GA应用到角色身上的&#xff0c;接下来这篇文章&#xff0c;将主要介绍一下GA的相关配置项。 在这之前&#xff0c;再多一嘴&#xff0c;你要能激活技能&#xff0c;首先要先应用到ASC上面&#xff0c;才能够被激活。 标签 之前介绍…...

提升自己最快的方式是什么?

提升自己最快的方式通常涉及到个人成长的各个方面&#xff0c;包括心理、情感、技能和知识等。根据查阅到的资料&#xff0c;以下是一些具体的方法和步骤&#xff0c;帮助你快速提升自己&#xff1a; 1. 培养屏蔽力 荷兰畅销书作家罗伊马丁纳提到&#xff0c;屏蔽力是个人成长…...

题目:一个5位数,判断它是不是回文数。即12321是回文数,个位与万位相同,十位与千位相同。

题目&#xff1a;一个5位数&#xff0c;判断它是不是回文数。即12321是回文数&#xff0c;个位与万位相同&#xff0c;十位与千位相同。    There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence…...

《HelloGitHub》第 96 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 https://github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 …...

C++tuple类型

tuple 类型 tuple是类似pair的模板。 每个pair的成员类型都不相同&#xff0c;但每个pair都恰好有两个成员。不同tuple类型的成员类型也不相同&#xff0c;但一个tuple可以有任意数量的成员。 每个确定的tuple类型的成员数目是固定的&#xff0c;但一个tuple类型的成员数目可…...

亚远景科技-浅谈ASPICE标准和ASPICE认证/评估

ASPICE&#xff08;Automotive SPICE&#xff09;是一种针对汽车行业的软件开发过程的评估模型&#xff0c;它旨在帮助汽车制造商和供应商提高软件开发过程的能力和质量&#xff0c;从而提升产品的质量、安全性和效率。 ASPICE标准涵盖了软件开发的各个阶段和活动&#xff0c;…...

PHP性能提升方案

一、背景与介绍 PHP语言开发效率高&#xff0c;特别应用于适合中小型项目&#xff0c;对于创业初期敏捷开发验证项目可行性或者Demo演示绝对占据优势。 但是随着现在Web应用的复杂性&#xff0c;针对项目要适应高并发、高流量的访问特性&#xff0c;PHP确实在性能方面相对Go、J…...

关系(二)利用python绘制热图

关系&#xff08;二&#xff09;利用python绘制热图 热图 &#xff08;Heatmap&#xff09;简介 热图适用于显示多个变量之间的差异&#xff0c;通过颜色判断彼此之间是否存在相关性。 快速绘制 基于seaborn import seaborn as sns import pandas as pd import numpy as np i…...

P8597 [蓝桥杯 2013 省 B] 翻硬币

# [蓝桥杯 2013 省 B] 翻硬币 ## 题目背景 小明正在玩一个“翻硬币”的游戏。 ## 题目描述 桌上放着排成一排的若干硬币。我们用 * 表示正面&#xff0c;用 o 表示反面&#xff08;是小写字母&#xff0c;不是零&#xff09;&#xff0c;比如可能情形是 **oo***oooo&#x…...

主流公链 - Fantom

Fantom&#xff1a;高性能的区块链协议 Fantom是一种开创性的区块链协议&#xff0c;旨在革新去中心化应用和数字金融领域 技术特点 共识机制 Lachesis协议&#xff1a;Fantom使用了Lachesis协议作为其共识算法。Lachesis是一种 异步拜占庭容错&#xff08;ABFT&#xff09;共…...

vue-quill-editor 富文本编辑器(可上传视频图片),组件挂载的方式实现

1.安装 npm install vue-quill-editor --save npm install quill-image-drop-module --save npm install quill-image-resize-module --save2.在组件下面新增组件 QlEditor (1)index.vue <template><div><div idquillEditorQiniu><!-- 基于element…...

入门编程第一步,从记住这些单词开始

** 入门编程第一步&#xff0c;从记住这些单词开始 ** 2023-10-18 一、交互式环境与 print 输出 1、print : 打印/输出 2、coding : 编码 3、syntax : 语法 4、error : 错误 5、invalid : 无效 6、idenfifier : 名称/标识符 7、character : 字符 二、字符串的操作&#x…...

[C++]使用OpenCV去除面积较小的连通域

这是后期补充的部分&#xff0c;和前期的代码不太一样 效果图 源代码 //测试 void CCutImageVS2013Dlg::OnBnClickedTestButton1() {vector<vector<Point> > contours; //轮廓数组vector<Point2d> centers; //轮廓质心坐标 vector<vector<Point&…...

vscode连接不上,终端ssh正常,一直输入密码正确但是无法登录

若是之前链结果突然等不上&#xff0c;使用第一个链接 若是第一次链接连不上&#xff0c;先使用第二个链接&#xff0c;在使用第一个链接 原因&#xff1a;原因是服务器端的wget命令不能使用&#xff0c;vscode需要服务器端下载个文件&#xff0c;无法下载就导致了如上的错误…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

计算机基础知识解析:从应用到架构的全面拆解

目录 前言 1、 计算机的应用领域&#xff1a;无处不在的数字助手 2、 计算机的进化史&#xff1a;从算盘到量子计算 3、计算机的分类&#xff1a;不止 “台式机和笔记本” 4、计算机的组件&#xff1a;硬件与软件的协同 4.1 硬件&#xff1a;五大核心部件 4.2 软件&#…...

基于PHP的连锁酒店管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

tomcat指定使用的jdk版本

说明 有时候需要对tomcat配置指定的jdk版本号&#xff0c;此时&#xff0c;我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...