做报名统计的网站微门户网站建设

news/2025/9/27 18:35:18/文章来源:
做报名统计的网站,微门户网站建设,学视频剪辑大概需要多少钱,四川省建筑人才网个人中心前面两篇文章记录了 Spring IOC 的相关知识#xff0c;本文记录 Spring 中的另一特性 AOP 相关知识。 部分参考资料#xff1a; 《Spring实战#xff08;第4版#xff09;》 《轻量级 JavaEE 企业应用实战#xff08;第四版#xff09;》 Spring 官方文档 W3CSchool Spri…前面两篇文章记录了 Spring IOC 的相关知识本文记录 Spring 中的另一特性 AOP 相关知识。 部分参考资料 《Spring实战第4版》 《轻量级 JavaEE 企业应用实战第四版》 Spring 官方文档 W3CSchool Spring教程 易百教程 Spring教程 一、AOP——另一种编程思想 1.1 什么是 AOP AOP Aspect Orient Programming,直译过来就是 面向切面编程。AOP 是一种编程思想是面向对象编程OOP的一种补充。面向对象编程将程序抽象成各个层次的对象而面向切面编程是将程序抽象成各个切面。 从《Spring实战第4版》图书中扒了一张图 从该图可以很形象地看出所谓切面相当于应用对象间的横切点我们可以将其单独抽象为单独的模块。 1.2 为什么需要 AOP 想象下面的场景开发中在多个模块间有某段重复的代码我们通常是怎么处理的显然没有人会靠“复制粘贴”吧。在传统的面向过程编程中我们也会将这段代码抽象成一个方法然后在需要的地方分别调用这个方法这样当这段代码需要修改时我们只需要改变这个方法就可以了。然而需求总是变化的有一天新增了一个需求需要再多出做修改我们需要再抽象出一个方法然后再在需要的地方分别调用这个方法又或者我们不需要这个方法了我们还是得删除掉每一处调用该方法的地方。实际上涉及到多个地方具有相同的修改的问题我们都可以通过 AOP 来解决。 1.3 AOP 实现分类 AOP 要达到的效果是保证开发者不修改源代码的前提下去为系统中的业务组件添加某种通用功能。AOP 的本质是由 AOP 框架修改业务组件的多个方法的源代码看到这其实应该明白了AOP 其实就是前面一篇文章讲的代理模式的典型应用。 按照 AOP 框架修改源代码的时机可以将其分为两类 静态 AOP 实现 AOP 框架在编译阶段对程序源代码进行修改生成了静态的 AOP 代理类生成的 *.class 文件已经被改掉了需要使用特定的编译器比如 AspectJ。动态 AOP 实现 AOP 框架在运行阶段对动态生成代理对象在内存中以 JDK 动态代理或 CGlib 动态地生成 AOP 代理类如 SpringAOP。 下面给出常用 AOP 实现比较 如不清楚动态代理的可参考我前面的一篇文章有讲解静态代理、JDK动态代理和 CGlib 动态代理。 静态代理和动态代理 https://www.cnblogs.com/joy99/p/10865391.html 二、AOP 术语 AOP 领域中的特性术语 通知Advice: AOP 框架中的增强处理。通知描述了切面何时执行以及如何执行增强处理。连接点join point: 连接点表示应用执行过程中能够插入切面的一个点这个点可以是方法的调用、异常的抛出。在 Spring AOP 中连接点总是方法的调用。切点PointCut: 可以插入增强处理的连接点。切面Aspect: 切面是通知和切点的结合。引入Introduction引入允许我们向现有的类添加新的方法或者属性。织入Weaving: 将增强处理添加到目标对象中并创建一个被增强的对象这个过程就是织入。 概念看起来总是有点懵并且上述术语不同的参考书籍上翻译还不一样所以需要慢慢在应用中理解。 三、初步认识 Spring AOP 3.1 Spring AOP 的特点 AOP 框架有很多种1.3节中介绍了 AOP 框架的实现方式有可能不同 Spring 中的 AOP 是通过动态代理实现的。不同的 AOP 框架支持的连接点也有所区别例如AspectJ 和 JBoss,除了支持方法切点它们还支持字段和构造器的连接点。而 Spring AOP 不能拦截对对象字段的修改也不支持构造器连接点,我们无法在 Bean 创建时应用通知。 3.2 Spring AOP 的简单例子 下面先上代码对着代码说比较好说看下面这个例子 这个例子是基于gradle创建的首先 build.gradle 文件添加依赖Maven也可以导入依赖 dependencies {compile org.springframework:spring-context:5.0.6.RELEASE }首先创建一个接口 IBuy.java package com.sharpcj.aopdemo.test1;public interface IBuy {String buy(); }Boy 和 Gril 两个类分别实现了这个接口 Boy.java package com.sharpcj.aopdemo.test1;import org.springframework.stereotype.Component;Component public class Boy implements IBuy {Overridepublic String buy() {System.out.println(男孩买了一个游戏机);return 游戏机;} }Girl.java package com.sharpcj.aopdemo.test1;import org.springframework.stereotype.Component;Component public class Girl implements IBuy {Overridepublic String buy() {System.out.println(女孩买了一件漂亮的衣服);return 衣服;} }配置文件, AppConfig.java package com.sharpcj.aopdemo;import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;Configuration ComponentScan(basePackageClasses {com.sharpcj.aopdemo.test1.IBuy.class}) public class AppConfig { }测试类 AppTest.java package com.sharpcj.aopdemo;import com.sharpcj.aopdemo.test1.Boy; import com.sharpcj.aopdemo.test1.Girl; import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class AppTest {public static void main(String[] args) {AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(AppConfig.class);Boy boy context.getBean(boy,Boy.class);Girl girl (Girl) context.getBean(girl);boy.buy();girl.buy();} }运行结果 这里运用SpringIOC里的自动部署。现在需求改变了我们需要在男孩和女孩的 buy 方法之前需要打印出“男孩女孩都买了自己喜欢的东西”。用 Spring AOP 来实现这个需求只需下面几个步骤 1、 既然用到 Spring AOP, 首先在 build.gralde 文件中引入相关依赖 dependencies {compile org.springframework:spring-context:5.0.6.RELEASEcompile org.springframework:spring-aspects:5.0.6.RELEASE }2、 定义一个切面类BuyAspectJ.java package com.sharpcj.aopdemo.test1;import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component;Aspect Component public class BuyAspectJ {Before(execution(* com.sharpcj.aopdemo.test1.IBuy.buy(..)))public void haha(){System.out.println(男孩女孩都买自己喜欢的东西);} }这个类我们使用了注解 Component 表明它将作为一个Spring Bean 被装配使用注解 Aspect 表示它是一个切面。 类中只有一个方法 haha 我们使用 Before 这个注解表示他将在方法执行之前执行。关于这个注解后文再作解释。 参数(execution(* com.sharpcj.aopdemo.test1.IBuy.buy(..))) 声明了切点表明在该切面的切点是com.sharpcj.aopdemo.test1.Ibuy这个接口中的buy方法。至于为什么这么写下文再解释。 3、 在配置文件中启用AOP切面功能 package com.sharpcj.aopdemo;import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy;Configuration ComponentScan(basePackageClasses {com.sharpcj.aopdemo.test1.IBuy.class}) EnableAspectJAutoProxy(proxyTargetClass true) public class AppConfig { } 我们在配置文件类增加了EnableAspectJAutoProxy注解启用了 AOP 功能参数proxyTargetClass的值设为了 true 。默认值是 false两者的区别下文再解释。 OK下面只需测试代码,运行结果如下 我们看到结果与我们需求一致我们并没有修改 Boy 和 Girl 类的 Buy 方法也没有修改测试类的代码几乎是完全无侵入式地实现了需求。这就是 AOP 的“神奇”之处。 四、通过注解配置 Spring AOP 4.1 通过注解声明切点指示器 Spring AOP 所支持的 AspectJ 切点指示器 在spring中尝试使用AspectJ其他指示器时将会抛出IllegalArgumentException异常。 当我们查看上面展示的这些spring支持的指示器时注意只有execution指示器是唯一的执行匹配而其他的指示器都是用于限制匹配的。这说明execution指示器是我们在编写切点定义时最主要使用的指示器在此基础上我们使用其他指示器来限制所匹配的切点。 下图的切点表达式表示当Instrument的play方法执行时会触发通知。 我们使用execution指示器选择Instrument的play方法方法表达式以 * 号开始标识我们不关心方法的返回值类型。然后我们指定了全限定类名和方法名。对于方法参数列表我们使用 .. 标识切点选择任意的play方法无论该方法的入参是什么。 多个匹配之间我们可以使用链接符 、||、来表示 “且”、“或”、“非”的关系。但是在使用 XML 文件配置时这些符号有特殊的含义所以我们使用 “and”、“or”、“not”来表示。 举例 限定该切点仅匹配的包是 com.sharpcj.aopdemo.test1,可以使用 execution(* com.sharpcj.aopdemo.test1.IBuy.buy(..)) within(com.sharpcj.aopdemo.test1.*) 在切点中选择 bean,可以使用 execution(* com.sharpcj.aopdemo.test1.IBuy.buy(..)) bean(girl) 修改 BuyAspectJ.java package com.sharpcj.aopdemo.test1;import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component;Aspect Component public class BuyAspectJ {Before(execution(* com.sharpcj.aopdemo.test1.IBuy.buy(..)) within(com.sharpcj.aopdemo.test1.*) bean(girl))public void hehe(){System.out.println(男孩女孩都买自己喜欢的东西);} } 此时切面只会对 Girl.java 这个类生效执行结果 细心的你可能发现了切面中的方法名已经被我悄悄地从haha改成了hehe丝毫没有影响结果说明方法名没有影响。和 Spring IOC 中用 java 配置文件装配 Bean 时用Bean 注解修饰的方法名一样没有影响。 4.2 通过注解声明 5 种通知类型 Spring AOP 中有 5 中通知类型分别如下 下面修改切面类 package com.sharpcj.aopdemo.test1;import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component;Aspect Component public class BuyAspectJ {Before(execution(* com.sharpcj.aopdemo.test1.IBuy.buy(..)))public void hehe() {System.out.println(before ...);}After(execution(* com.sharpcj.aopdemo.test1.IBuy.buy(..)))public void haha() {System.out.println(After ...);}AfterReturning(execution(* com.sharpcj.aopdemo.test1.IBuy.buy(..)))public void xixi() {System.out.println(AfterReturning ...);}Around(execution(* com.sharpcj.aopdemo.test1.IBuy.buy(..)))public void xxx(ProceedingJoinPoint pj) {try {System.out.println(Around aaa ...);pj.proceed();System.out.println(Around bbb ...);} catch (Throwable throwable) {throwable.printStackTrace();}}} 为了方便看效果,我们测试类中只要 Boy 类: package com.sharpcj.aopdemo;import com.sharpcj.aopdemo.test1.Boy; import com.sharpcj.aopdemo.test1.Girl; import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class AppTest {public static void main(String[] args) {AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(AppConfig.class);Boy boy context.getBean(boy,Boy.class);Girl girl (Girl) context.getBean(girl);boy.buy();// girl.buy();} } 执行结果如下 结果显而易见。指的注意的是 Around 修饰的环绕通知类型是将整个目标方法封装起来了在使用时我们传入了 ProceedingJoinPoint 类型的参数这个对象是必须要有的并且需要调用 ProceedingJoinPoint 的 proceed() 方法。 如果没有调用 该方法执行结果为 Around aaa ... Around bbb ... After ... AfterReturning ...可见如果不调用该对象的 proceed() 方法表示原目标方法被阻塞调用当然也有可能你的实际需求就是这样。 4.3 通过注解声明切点表达式 如你看到的上面我们写的多个通知使用了相同的切点表达式对于像这样频繁出现的相同的表达式我们可以使用 Pointcut注解声明切点表达式然后使用表达式修改代码如下 BuyAspectJ.java package com.sharpcj.aopdemo.test1;import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component;Aspect Component public class BuyAspectJ {Pointcut(execution(* com.sharpcj.aopdemo.test1.IBuy.buy(..)))public void point(){}Before(point())public void hehe() {System.out.println(before ...);}After(point())public void haha() {System.out.println(After ...);}AfterReturning(point())public void xixi() {System.out.println(AfterReturning ...);}Around(point())public void xxx(ProceedingJoinPoint pj) {try {System.out.println(Around aaa ...);pj.proceed();System.out.println(Around bbb ...);} catch (Throwable throwable) {throwable.printStackTrace();}} } 程序运行结果没有变化。 这里我们使用 Pointcut(execution(* com.sharpcj.aopdemo.test1.IBuy.buy(..))) public void point(){} 声明了一个切点表达式该方法 point 的内容并不重要方法名也不重要实际上它只是作为一个标识供通知使用。 4.4 通过注解处理通知中的参数 上面的例子我们要进行增强处理的目标方法没有参数下面我们来说说有参数的情况并且在增强处理中使用该参数。 下面我们给接口增加一个参数表示购买所花的金钱。通过AOP 增强处理如果女孩买衣服超过了 68 元就可以赠送一双袜子。 更改代码如下 IBuy.java package com.sharpcj.aopdemo.test1;public interface IBuy {String buy(double price); } Girl.java package com.sharpcj.aopdemo.test1;import org.springframework.stereotype.Component;Component public class Girl implements IBuy {Overridepublic String buy(double price) {System.out.println(String.format(女孩花了%s元买了一件漂亮的衣服, price));return 衣服;} } Boy.java package com.sharpcj.aopdemo.test1;import org.springframework.stereotype.Component;Component public class Boy implements IBuy {Overridepublic String buy(double price) {System.out.println(String.format(男孩花了%s元买了一个游戏机, price));return 游戏机;} } 再看 BuyAspectJ 类我们将之前的通知都注释掉。用一个环绕通知来实现这个功能 package com.sharpcj.aopdemo.test1;import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component;Aspect Component public class BuyAspectJ {/*Pointcut(execution(* com.sharpcj.aopdemo.test1.IBuy.buy(..)))public void point(){}Before(point())public void hehe() {System.out.println(before ...);}After(point())public void haha() {System.out.println(After ...);}AfterReturning(point())public void xixi() {System.out.println(AfterReturning ...);}Around(point())public void xxx(ProceedingJoinPoint pj) {try {System.out.println(Around aaa ...);pj.proceed();System.out.println(Around bbb ...);} catch (Throwable throwable) {throwable.printStackTrace();}}*/Pointcut(execution(String com.sharpcj.aopdemo.test1.IBuy.buy(double)) args(price) bean(girl))public void gif(double price) {}Around(gif(price))public String hehe(ProceedingJoinPoint pj, double price){try {pj.proceed();if (price 68) {System.out.println(女孩买衣服超过了68元赠送一双袜子);return 衣服和袜子;}} catch (Throwable throwable) {throwable.printStackTrace();}return 衣服;} } 前文提到当不关心方法返回值的时候我们在编写切点指示器的时候使用了 * 当不关心方法参数的时候我们使用了 ..。现在如果我们需要传入参数并且有返回值的时候则需要使用对应的类型。在编写通知的时候我们也需要声明对应的返回值类型和参数类型。 测试类AppTest.java package com.sharpcj.aopdemo;import com.sharpcj.aopdemo.test1.Boy; import com.sharpcj.aopdemo.test1.Girl; import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class AppTest {public static void main(String[] args) {AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(AppConfig.class);Boy boy context.getBean(boy,Boy.class);Girl girl (Girl) context.getBean(girl);String boyBought boy.buy(35);String girlBought girl.buy(99.8);System.out.println(男孩买到了 boyBought);System.out.println(女孩买到了 girlBought);} } 测试结果 可以看到我们成功通过 AOP 实现了需求并将结果打印了出来。 4.5 通过注解配置织入的方式 前面还有一个遗留问题在配置文件中我们用注解 EnableAspectJAutoProxy() 启用Spring AOP 的时候我们给参数 proxyTargetClass 赋值为 true,如果我们不写参数默认为 false。这个时候运行程序程序抛出异常 这是一个强制类型转换异常。为什么会抛出这个异常呢或许已经能够想到这跟Spring AOP 动态代理的机制有关这个 proxyTargetClass 参数决定了代理的机制。当这个参数为 false 时 通过jdk的基于接口的方式进行织入这时候代理生成的是一个接口对象将这个接口对象强制转换为实现该接口的一个类自然就抛出了上述类型转换异常。 反之proxyTargetClass 为 true则会使用 cglib 的动态代理方式。这种方式的缺点是拓展类的方法被final修饰时无法进行织入。 测试一下我们将 proxyTargetClass 参数设为 true同时将 Girl.java 的 Buy 方法用 final 修饰 AppConfig.java package com.sharpcj.aopdemo;import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy;Configuration ComponentScan(basePackageClasses {com.sharpcj.aopdemo.test1.IBuy.class}) EnableAspectJAutoProxy(proxyTargetClass true) public class AppConfig { } Girl.java package com.sharpcj.aopdemo.test1;import org.springframework.stereotype.Component;Component public class Girl implements IBuy {Overridepublic final String buy(double price) {System.out.println(String.format(女孩花了%s元买了一件漂亮的衣服, price));return 衣服;} } 此时运行结果 可以看到我们的切面并没有织入生效。 五、通过 XML 配置文件声明切面 前面的示例中我们已经展示了如何通过注解配置去声明切面下面我们看看如何在 XML 文件中声明切面。下面先列出 XML 中声明 AOP 的常用元素 我们依然可以使用 元素他能够自动代理AspectJ注解的通知类。 5.1 XML 配置文件中切点指示器 在XML配置文件中切点指示器表达式与通过注解配置的写法基本一致区别前面有提到即XML文件中需要使用 “and”、“or”、“not”来表示 “且”、“或”、“非”的关系。 5.2 XML 文件配置 AOP 实例 下面我们不使用任何注解改造上面的例子 BuyAspectJ.java package com.sharpcj.aopdemo.test2;import org.aspectj.lang.ProceedingJoinPoint;public class BuyAspectJ {public void hehe() {System.out.println(before ...);}public void haha() {System.out.println(After ...);}public void xixi() {System.out.println(AfterReturning ...);}public void xxx(ProceedingJoinPoint pj) {try {System.out.println(Around aaa ...);pj.proceed();System.out.println(Around bbb ...);} catch (Throwable throwable) {throwable.printStackTrace();}} } 在 Resource 目录下新建一个配置文件 aopdemo.xml ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdbean idboy classcom.sharpcj.aopdemo.test2.Boy/beanbean idgirl classcom.sharpcj.aopdemo.test2.Girl/beanbean idbuyAspectJ classcom.sharpcj.aopdemo.test2.BuyAspectJ/beanaop:config proxy-target-classtrueaop:aspect idqiemian refbuyAspectJaop:before pointcutexecution(* com.sharpcj.aopdemo.test2.IBuy.buy(..)) methodhehe/aop:after pointcutexecution(* com.sharpcj.aopdemo.test2.IBuy.buy(..)) methodhaha/aop:after-returning pointcutexecution(* com.sharpcj.aopdemo.test2.IBuy.buy(..)) methodxixi/aop:around pointcutexecution(* com.sharpcj.aopdemo.test2.IBuy.buy(..)) methodxxx//aop:aspect/aop:config /beans 这里分别定义了一个切面里面包含四种类型的通知。 测试文件中使用 ClassPathXmlApplicationContext context new ClassPathXmlApplicationContext(aopdemo.xml); 来获取 ApplicationContext其它代码不变。 5.3 XML 文件配置声明切点 对于频繁重复使用的切点表达式我们也可以声明成切点。 配置文件如下aopdemo.xml ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdbean idboy classcom.sharpcj.aopdemo.test2.Boy/beanbean idgirl classcom.sharpcj.aopdemo.test2.Girl/beanbean idbuyAspectJ classcom.sharpcj.aopdemo.test2.BuyAspectJ/beanaop:config proxy-target-classtrueaop:pointcut idapoint expressionexecution(* com.sharpcj.aopdemo.test2.IBuy.buy(..))/aop:aspect idqiemian refbuyAspectJaop:before pointcut-refapoint methodhehe/aop:after pointcut-refapoint methodhaha/aop:after-returning pointcut-refapoint methodxixi/aop:around pointcut-refapoint methodxxx//aop:aspect/aop:config /beans 5.4 XML文件配置为通知传递参数 BuyAspectJ.java package com.sharpcj.aopdemo.test2;import org.aspectj.lang.ProceedingJoinPoint;public class BuyAspectJ { public String hehe(ProceedingJoinPoint pj, double price){try {pj.proceed();if (price 68) {System.out.println(女孩买衣服超过了68元赠送一双袜子);return 衣服和袜子;}} catch (Throwable throwable) {throwable.printStackTrace();}return 衣服;} } aopdemo.xml ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdbean idboy classcom.sharpcj.aopdemo.test2.Boy/beanbean idgirl classcom.sharpcj.aopdemo.test2.Girl/beanbean idbuyAspectJ classcom.sharpcj.aopdemo.test2.BuyAspectJ/beanaop:config proxy-target-classtrueaop:pointcut idapoint expressionexecution(String com.sharpcj.aopdemo.test2.IBuy.buy(double)) and args(price) and bean(girl)/aop:aspect idqiemian refbuyAspectJaop:around pointcut-refapoint methodhehe//aop:aspect/aop:config /beans5.5 Xml 文件配置织入的方式 同注解配置类似, CGlib 代理方式 aop:config proxy-target-classtrue /aop:configJDK 代理方式 aop:config proxy-target-classfalse /aop:config六、总结 本文简单记录了 AOP 的编程思想然后介绍了 Spring 中 AOP 的相关概念以及通过注解方式和XML配置文件两种方式使用 Spring AOP进行编程。 相比于 AspectJ 的面向切面编程Spring AOP 也有一些局限性但是已经可以解决开发中的绝大多数问题了如果确实遇到了 Spring AOP 解决不了的场景我们依然可以在 Spring 中使用 AspectJ 来解决。

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

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

相关文章

net网站开发教程简易微网站模板

构造器最大的作用:创建对象. 为什么使用反射创建对象,为什么不直接来new呢? 在框架中,提供给我们的都是字符串. ----------------------------------------------------------- 使用反射创建对象: 步骤: 1);找到构造器所在类的字节码对象. 2):获取构造器对象. 3):使用反射…

安全可信网站营销活动策划方案模板

前言 Python可以用于复杂的数据分析和Web开发项目,还能以极少的代码行数完成令人惊叹的任务。本文将分享25个简短的Python代码示例,用来展示Python编程语言的魅力和效率。 1.列表推导式 Python的列表推导式提供了一种优雅的方法来创建列表。 # 将一个…

完整教程:微论-神经网络的亲情密码,权重矩阵的家庭关系论

完整教程:微论-神经网络的亲情密码,权重矩阵的家庭关系论2025-09-27 18:26 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !importan…

Ansible + Docker 部署 Apache Nifi 1.28 单用户集群

Ansible + Docker 部署 Apache Nifi 1.28 单用户集群1. 准备工作 1.1 主机列表IP 主机名 内存(GB) CPU核数 磁盘 操作系统 CPU 架构10.0.0.13 arc-pro-dc01my.registry.com 16 1 500GB CentOS 7.9.2009 x86_6410.0.…

候机的队伍

候机的队伍今天乘机,小朋友们很激动地早早地去排队了。我苦口婆心地教育他们,不需要这么早排队。因为座位都是固定的,而需要早排队的理由只有两个: 1. 带了较多行李,需要早点登机占个位置。 2. 缓解焦虑,早点坐上…

个人网站怎么做支付功能抖音代运营合作协议免费

聚苯乙烯(Polystyrene,简称PS)是一种常见的合成聚合物,属于热塑性塑料。它是由苯乙烯单体聚合而成的,具有轻质、透明或半透明、电绝缘性好等特点。常见: 包装材料白色泡沫塑料(EPS,用于包装、保…

网站推广策划的思路包括哪些内容广州网站建设功能

来源:半导体行业观察摘 要在本项目中,我们提出了一种基于学习的芯片布局方法,这是芯片设计过程中最复杂,最耗时的阶段之一。与以前的方法不同,我们的方法具有从过去的经验中学习并随着时间的推移而不断改进的能力。特别…

Keil uVision5 设置 hex 输出路径,不放Objects目录下

前言全局说明最近从 keil 2 换到 keil5, 新建项目后编译输出的 .hex 文件被放到 Objects目录下,找着不方便。一、说明 1.1 环境: Windows 7 旗舰版二、修改路径 2.1 打开项目设置选项 从工具栏打开或 从菜单里打开2.…

深入解析:【Linux】进程概念(六):进程地址空间深度解析:虚拟地址与内存管理的奥秘

深入解析:【Linux】进程概念(六):进程地址空间深度解析:虚拟地址与内存管理的奥秘pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; f…

深入解析:Metal - 5.深入剖析 3D 变换

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

垃圾收集器G1ZGC详解

垃圾收集器G1&ZGC详解 一、G1 收集器(-XX:+UseG1GC) G1(Garbage-First)是面向多处理器、大内存的服务器级收集器,核心目标是可预测的 GC 停顿时间与高吞吐量平衡。1. 核心特性Region 划分:将 Java 堆划分为最…

菠菜网站怎么做外贸网站该怎么做

控制actor在level中沿着一个spline path运动。 由finterp to 函数的输出数值来控制每一帧actor运动的距离。 从开始位置到spline path的终点的时间,是1/interp speed。假如我们控制actor从开头到终点运动的总时间是1秒,那么 interp speed就传入0.5&#…

Godot Outline

Godot OutlineGodot 4.5 这几天更新了,补全了模板缓冲, 在渲染Depth Buffer时,一般使用D32S8的类似格式。在Godot中,原本Depth Buffer就只渲染了Depth,因此S8的通道没有被使用。Stencil即特定材质可以向这个通道里…

油猴脚本(tampermonkey)离线安装文件下载,带油猴(tampermonkey)插件清单

油猴插件(Tampermonkey)是一款浏览器扩展程序(也称为“用户脚本管理器”),主要是在浏览器中安装和运行自定义脚本,用于修改或增强网页功能。目前支持Chrome、Firefox、Edge、Safari等主流浏览器,基本就是丰富浏…

树在线网页制作网站wordpress目录在哪里

一款博客网站源码 源码软件库 为大家内置了主题 清爽又强大真正的永久可用的一条源码,该版本为整合版本,内置了Joe主题,搭建后直接启用即可~ 安装环境要求: PHP 7.2 以上 MySQL, PostgreSQL, SQLite 任意一种数据库支持&#xff…

海口建网站 模板c 网站开发培训

文章目录 文章介绍下载连接安装教程 文章介绍 安装Qt5.12.2 下载连接 点击官网下载 安装包下载完毕 安装教程 点开设置,添加临时储存库,复制连接“https://download.qt.io/online/qtsdkrepository/windows_x86/root/qt/” 点击测试&#xff0…

SentinelOne与MITRE ATTCK企业版2025评估的深度解析

本文深入探讨SentinelOne对MITRE ATT&CK评估体系的立场转变,分析企业级网络安全评估标准的发展趋势,并揭示安全厂商在资源调配与产品路线图之间的战略平衡。文章聚焦于现代网络安全技术演进与实战化评估体系的内…

详细介绍:Docker的介绍

详细介绍:Docker的介绍pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", &qu…

详细介绍:【汽车篇】基于深度学习的2D+3D整车漆面外观缺陷检测

详细介绍:【汽车篇】基于深度学习的2D+3D整车漆面外观缺陷检测pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Co…

深入解析:网线传输距离限制 | 理论基础 / 实际应用 | 双绞线分类与特性 / 水晶头制作

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …