当前位置: 首页 > 编程日记 > 正文

Spring Aop的应用

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

AOP的基本概念

  • 连接点( Jointpoint) : 表示需要在程序中插入横切关注点的扩展点,连接点可能是类初始化、方法执行、 方法调用、字段调用或处理异常等等, Spring 只支持方法执行连接点, 在 AOP 中表示为“在哪里干” ;

  • 切入点( Pointcut) : 选择一组相关连接点的模式, 即可以认为连接点的集合,Spring 支持 perl5 正则表达式和 AspectJ 切入点模式, Spring 默认使用 AspectJ 语法, 在 AOP 中表示为“在哪里干的集合” ;

  • 通知( Advice) : 在连接点上执行的行为, 通知提供了在 AOP 中需要在切入点所选择的连接点处进行扩展现有行为的手段; 包括前置通知( before advice)、后置通知(after advice)、环绕通知( around advice), 在 Spring 中通过代理模式实现AOP,并通过拦截器模式以环绕连接点的拦截器链织入通知; 在 AOP 中表示为“干什么”;

  • 方面/切面( Aspect): 横切关注点的模块化,可以认为是通知、引入和切入点的组合; 在 Spring 中可以使用 Schema 和@AspectJ 方式进行组织实现; 在 AOP 中表示为“在哪干和干什么集合”

  • 引入( inter-type declaration) : 也称为内部类型声明, 为已有的类添加额外新的字段或方法, Spring 允许引入新的接口(必须对应一个实现)到所有被代理对象(目标对象) , 在 AOP 中表示为“干什么(引入什么) ” ;

  • 目标对象( Target Object) : 需要被织入横切关注点的对象,即该对象是切入点选择的对象,需要被通知的对象,从而也可称为“被通知对象”;由于 Spring AOP通过代理模式实现,从而这个对象永远是被代理对象, 在 AOP 中表示为“对谁干” ;

  • AOP 代理( AOP Proxy) : AOP 框架使用代理模式创建的对象,从而实现在连接点处插入通知(即应用切面) ,就是通过代理来对目标对象应用切面。在 Spring中, AOP 代理可以用 JDK 动态代理或 CGLIB 代理实现,而通过拦截器模型应用切面。

  • 织入( Weaving) : 织入是一个过程,是将切面应用到目标对象从而创建出 AOP代理对象的过程, 织入可以在编译期、类装载期、运行期进行。

Spring有哪些通知类型呢?

  • 前置通知( Before Advice) :在切入点选择的连接点处的方法之前执行的通知,该通知不影响正常程序执行流程(除非该通知抛出异常,该异常将中断当前方法链的执行而返回)。

  • 后置通知( After Advice) : 在切入点选择的连接点处的方法之后执行的通知,包括如下类型的后置通知:

    1. 后置返回通知( After returning Advice) :在切入点选择的连接点处的方法正常执行完毕时执行的通知, 必须是连接点处的方法没抛出任何异常正常返回时才调用后置通知。

    2. 后置异常通知( After throwing Advice) : 在切入点选择的连接点处的方法抛出异常返回时执行的通知, 必须是连接点处的方法抛出任何异常返回时才调用异常通知。

    3. 后置最终通知( After finally Advice) : 在切入点选择的连接点处的方法返回时执行的通知,不管抛没抛出异常都执行,类似于 Java 中的 finally 块。

  • 环绕通知( Around Advices): 环绕着在切入点选择的连接点处的方法所执行的通知,环绕通知可以在方法调用之前和之后自定义任何行为,并且可以决定是否执行连接点处的方法、替换返回值、抛出异常等等。

在 AOP 中,通过切入点选择目标对象的连接点,然后在目标对象的相应连接点处织入通知,而切入点和通知就是切面(横切关注点),而在目标对象连接点处应用切面的实现方式是通过 AOP 代理对象。

基于注解的AOP编程

基于注解的编程,需要依赖AspectJ框架(java中最流行的aop框架)。 第一步:导入AspectJ的jar包,该框架只有Spring 2.0以上才支持。

<dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.7.3</version>
</dependency>
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.7.3</version><scope>runtime</scope>
</dependency>

第三步:切面类,该类有什么特点?首先它必须是IOC的bean,还要声明它是AspectJ切面,最后还可以定义切面的优先级Order(非必填)

通知有五种注解 @Before :前置通知的注解,在目标方法执行前调用

@After:后置通知的注解, 在目标方法执行后调用,即使程序抛出异常都会调用

@AfterReturning:返回通知的注解, 在目标方法成功执行后调用,如果程序出错则不会调用

@AfterThrowing:异常通知的注解, 在目标方法出现指定异常时调用

@Around:环绕通知的注解,很强大(相当于前四个通知的组合),但用的不多。

环绕通知

import java.util.Arrays;
import java.util.List;/*** @program: ssm* @description: 环绕通知* @author: lee* @create: 2019-03-14**/
@Order(2)
@Aspect
@Component
public class AroundAspect {/*** 环绕通知,很强大,但用的不多。 用环绕通知测试Order的优先级看的不明显(这里是笔者的失误)* 环绕通知需要用ProceedingJoinPoint 类型的参数*/@Around("execution(* com.*.aspect.*.*(..))")public Object aroundAdvice(ProceedingJoinPoint joinPoint) {Object result = null;String methodName = joinPoint.getSignature().getName();List<Object> args = Arrays.asList(joinPoint.getArgs());try {System.out.println("@Around 前置通知 : 方法名 【 " + methodName + " 】and args are " + args);result = joinPoint.proceed();System.out.println("@Around 返回通知 : 方法名 【 " + methodName + " 】and args are " + args + " , result is " + result);} catch (Throwable e) {e.printStackTrace();System.out.println("@Around 异常通知 : 方法名 【 " + methodName + " 】and  exception is " + e);}System.out.println("@Around 后置通知 : 方法名 【 " + methodName + " 】and args are " + args);return result;}
}    

拦截对象

package com.plantform.aspect;import org.springframework.stereotype.Component;/*** @program: ssm* @description: 切面类* @author: lee* @create: 2019-03-14**/
public class AspectMethod {public int add(int a, int b) {System.out.println("add 方法执行了 ----> " + (a + b));return (a + b);}public int division(int a, int b) {System.out.println("division 方法执行了 ----> " + (a / b));return (a / b);}}    

拦截通知

package com.plantform.aspect;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;import java.util.Arrays;
import java.util.List;/*** @program: ssm* @Order(n) : 切面的优先级,n越小,级别越高* @Aspect:声明该类是一个切面* @Component:切面必须是 IOC 中的 bean* @author: lee* @create: 2019-03-14**/
@Order(1)
@Aspect
@Component
public class LogAspect {/*** 前置通知的注解,在目标方法执行前调用* execution最基础的表达式语法。* 注意点:* 1. 方法里面不能有行参,及add(int a, int b) 这是会报错的。* 2. int(方法的返回值),add(方法名) 可以用 * 抽象化。甚至可以将类名抽象,指定该包下的类。* 3. (int, int) 可以用(..)代替,表示匹配任意数量的参数* 4. 被通知的对象(Target),建议加上包的路径*/@Before(value = "execution(* com.*.aspect.*.*(..))")public void beforeAdvice(JoinPoint joinPoint) {/*** 连接点 joinPoint:add方法就是连接点* getName获取的是方法名,是英文的,可以通过国际化转换对应的中文比较好。*/String methodName = joinPoint.getSignature().getName();List<Object> args = Arrays.asList(joinPoint.getArgs());System.out.println("@Before 前置通知 : 方法名 【 " + methodName + " 】and args are " + args);}/*** 后置通知的注解, 在目标方法执行后调用,即使是程序出错都会调用* 这里将 方法的返回值 和 CalculatorImp类下所有的方法,以及方法的形参 都抽象了*/@After(value = "execution(* com.*.aspect.*.*(..))")public void afterAdvice(JoinPoint joinPoint) {String methodName = joinPoint.getSignature().getName();List<Object> args = Arrays.asList(joinPoint.getArgs());System.out.println("@After 后置通知 : 方法名 【 " + methodName + " 】and args are " + args);}/*** 重用切入点定义:声明切入点表达式。该方法里面不建议添加其他代码*/@Pointcut("execution(* com.*.aspect.*.*(..))")public void declareExecutionExpression(){}/*** 返回通知的注解, 在目标方法成功执行后调用,如果程序出错则不会调用* returning="result" 和 形参 result 保持一致*/@AfterReturning(value="declareExecutionExpression()", returning="result")public void afterRunningAdvice(JoinPoint joinPoint, Object result) {String methodName = joinPoint.getSignature().getName();List<Object> args = Arrays.asList(joinPoint.getArgs());System.out.println("@AfterReturning 返回通知 : 方法名 【 " + methodName + " 】and args are " + args + " , result is " + result);}/*** 异常通知的注解, 在目标方法出现指定异常时调用* throwing="exception" 和 形参 exception 保持一致 , 且目标方法出了Exception(可以是其他异常)异常才会调用。*/@AfterThrowing(value="declareExecutionExpression()", throwing="exception")public void afterThrowingAdvice(JoinPoint joinPoint, Exception exception) {String methodName = joinPoint.getSignature().getName();System.out.println("@AfterThrowing 异常通知 : 方法名 【 " + methodName + " 】and  exception is " + exception);}
}    

运行方法

/*** @program: ssm* @description:* @author: lee* @create: 2019-03-14**/
@Controller
public class MainAspect {@RequestMapping("/static/index")@ResponseBodypublic String main(String[] args) {AspectMethod aspectMethod=new AspectMethod();aspectMethod.add(11, 12);aspectMethod.division(21, 3);//aspectMethod.division(21, 0);return "执行完了";}
}    

输出结果

@Before 前置通知 : 方法名 【 main 】and args are [null]
@Around 前置通知 : 方法名 【 main 】and args are [null]
add 方法执行了 ----> 23
division 方法执行了 ----> 7
@Around 返回通知 : 方法名 【 main 】and args are [null] , result is 执行成功
@Around 后置通知 : 方法名 【 main 】and args are [null]
@After 后置通知 : 方法名 【 main 】and args are [null]
@AfterReturning 返回通知 : 方法名 【 main 】and args are [null] , result is 执行成功

基于xml的AOP编程

第一步:核心文件applicationContext.xml, 首先是配置三个bean,方便是两个切面类,和一个方法类。 然后配置AOP, aop:config:注明开始配置AOP

aop:pointcut:配置切点重用表达式,expression的值是具体的表达式,id 该aop:pointcut的唯一标识,

aop:aspect:配置切面,ref的值引用相关切面类的bean,order设置优先级(也可以不设置)。

五种通知的配置:aop:before,aop:after,aop:after-returning,aop:after-throwing,aop:around。method的值就是对应的方法,poincut-ref的值要引用 aop:pointcut 的id。其中有两个比较特殊:aop:after-returning 要多配置一个returning,其中returning的值要和对应方法的形参保持一致。同理aop:after-throwing 也要多配置一个throwing,其中throwing的值也要和对应方法的形参保持一致。不然执行程序会报错。

<?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.xsd  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">  <bean id="calculator" class="com.atguigu.spring.my.xml.CalculatorImp"></bean>  <bean id="loggerAspect" class="com.atguigu.spring.my.xml.LoggerAspect"></bean>  <bean id="aroundAspect" class="com.atguigu.spring.my.xml.AroundAspect"></bean>  <!-- AOP配置 -->  <aop:config>  <!-- 配置切点表达式 类似注解的重用表达式-->  <aop:pointcut expression="execution(* com.atguigu.spring.my.xml.CalculatorImp.*(..))"   id="pointcut"/>  <!-- 配置切面及通知  method的值就是 loggerAspect类中的值-->  <aop:aspect ref="loggerAspect" order="2">  <aop:before method="beforeAdvice" pointcut-ref="pointcut"/>  <aop:after method="afterAdvice" pointcut-ref="pointcut"/>  <aop:after-returning method="afterRunningAdvice" pointcut-ref="pointcut" returning="result"/>  <aop:after-throwing method="afterThrowingAdvice" pointcut-ref="pointcut" throwing="exception"/>  </aop:aspect>  <aop:aspect ref="aroundAspect" order="1">  <!-- <aop:around method="aroundAdvice" pointcut-ref="pointcut"/>  -->  </aop:aspect>  </aop:config>  </beans>  

下面几个类,就是脱去了所有注解的外衣,采用通过配置的xml,实现AOP编程。

public interface Calculator {  public int add(int a, int b);  public int division(int a, int b);  }  public class CalculatorImp implements Calculator {  @Override  public int add(int a, int b) {  System.out.println("add 方法执行了 ----> " + (a + b));  return (a + b);  }  @Override  public int division(int a, int b) {  System.out.println("division 方法执行了 ----> " + (a / b));  return (a / b);  }  }  import java.util.Arrays;  
import java.util.List;  
import org.aspectj.lang.JoinPoint;  public class LoggerAspect {  public void beforeAdvice(JoinPoint joinPoint) {  String methodName = joinPoint.getSignature().getName();   List<Object> args = Arrays.asList(joinPoint.getArgs());  System.out.println("Before 前置通知 : 方法名 【 " + methodName + " 】and args are " + args);  }  public void afterAdvice(JoinPoint joinPoint) {  String methodName = joinPoint.getSignature().getName();   List<Object> args = Arrays.asList(joinPoint.getArgs());  System.out.println("After 后置通知 : 方法名 【 " + methodName + " 】and args are " + args);  }  public void afterRunningAdvice(JoinPoint joinPoint, Object result) {  String methodName = joinPoint.getSignature().getName();   List<Object> args = Arrays.asList(joinPoint.getArgs());  System.out.println("AfterReturning 返回通知 : 方法名 【 " + methodName + " 】and args are " + args + " , result is " + result);  }  public void afterThrowingAdvice(JoinPoint joinPoint, Exception exception) {  String methodName = joinPoint.getSignature().getName();   System.out.println("AfterThrowing 异常通知 : 方法名 【 " + methodName + " 】and  exception is " + exception);  }  }  import java.util.Arrays;  
import java.util.List;  
import org.aspectj.lang.ProceedingJoinPoint;  public class AroundAspect {  public Object aroundAdvice(ProceedingJoinPoint joinPoint) {  Object result = null;  String methodName = joinPoint.getSignature().getName();   List<Object> args = Arrays.asList(joinPoint.getArgs());  try {  System.out.println("@Around 前置通知 : 方法名 【 " + methodName + " 】and args are " + args);  result = joinPoint.proceed();  System.out.println("@Around 返回通知 : 方法名 【 " + methodName + " 】and args are " + args + " , result is " + result);  } catch (Throwable e) {  e.printStackTrace();  System.out.println("@Around 异常通知 : 方法名 【 " + methodName + " 】and  exception is " + e);  }  System.out.println("@Around 后置通知 : 方法名 【 " + methodName + " 】and args are " + args);  return result;  }  }  import org.springframework.context.support.ClassPathXmlApplicationContext;  public class Main {  public static void main(String[] args) {  ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");  Calculator calculator = (Calculator) ctx.getBean("calculator");  calculator.add(11, 12);  calculator.division(21, 3); // 测试时,将被除数换成0,可以测试AfterReturning ,After 和 AfterThrowing  ctx.close();  }  }  

输出结果

Before 前置通知 : 方法名 【 add 】and args are [11, 12]  
add 方法执行了 ----> 23  
After 后置通知 : 方法名 【 add 】and args are [11, 12]  
AfterReturning 返回通知 : 方法名 【 add 】and args are [11, 12] , result is 23  
Before 前置通知 : 方法名 【 division 】and args are [21, 3]  
division 方法执行了 ----> 7  
After 后置通知 : 方法名 【 division 】and args are [21, 3]  
AfterReturning 返回通知 : 方法名 【 division 】and args are [21, 3] , result is 7  

转载于:https://my.oschina.net/jiansin/blog/3022375

相关文章:

Apache Tomcat 7.x 概述

前言 Tomcat 一直是Java web程序的首选应用服务器&#xff0c;现在已经更新到7.x版本了。如果你还使用老版本&#xff0c;那么你赶快更新到最新版本吧&#xff0c;他改善了不性能&#xff0c;修复了很多BUG。下面我从官网&#xff0c;简单翻译了一下7.x的特性&#xff0c;给你一…

linux mysql清除数据库所有表_MySQL修复指定数据库下的所有表

mysql,mariadb,percona这几天数据库频繁crash&#xff0c;查看日志发现类似如下的错误:[ERROR] mysqld: Table ./database/pre_forum_forumfield is marked as crashed and should be repaired1[ERROR]mysqld:Table./database/pre_forum_forumfieldismarkedascrashedandshouldb…

Java基础知识强化之IO流笔记03:throws的方式处理异常

1. 什么时候使用throws ? &#xff08;1&#xff09;定义功能方法时候&#xff0c;需要把出现的问题暴露出来&#xff0c;让调用者去处理。那么就通过throws在方法上标识。 &#xff08;2&#xff09;有时候&#xff0c;我们是可以对异常进行处理的&#xff0c;但是又有些时候…

silverlight学习之storyboard (动画)

利用silverlight的storyboard可以很方便的制作一些简单的“动画”&#xff0c;比如控制一些控件double类型或者color类型的属性值的变化。下面简单地说其中最简单的两个方面&#xff1a;DoubleAnimation&#xff08;控制控件double类型的属性&#xff09;和ColorAnimation&…

记一次Sonar执行失败的修复

为什么80%的码农都做不了架构师&#xff1f;>>> 前提 在提高代码质量方面公司采用的是JenkinsSonar的方案&#xff0c;通过设定扫描规则对现有代码工程进行扫描。代码扫描后会产生不同级别的问题&#xff0c;例如Bugs、漏洞、坏味道等。针对每个工程的发布是用…

java用if语句调用方法_J2SE中main函数中的if语句想要调用另一个类的方法怎么能实现?...

日常生活中&#xff0c;要完成一件复杂的功能&#xff0c;我们总是习惯把“大功能”分解为多个“小功能”以实现。在C程序的世界里&#xff0c;“功能”可称呼为“函数”&#xff0c;因此“函数”其实就是一段实现了某种功能的代码&#xff0c;并且可以供其它代码调用。一个程序…

Creating Apps With Material Design —— Defining Custom Animations

转载请注明 http://blog.csdn.net/eclipsexys 翻译自Developer Android&#xff0c;时间仓促&#xff0c;有翻译问题请留言指出。谢谢定义动画在材料设计动画让用户与您的应用程序进行交互时&#xff0c;为他们的行为提供反馈。并提供可视化的连续性。该材料的主题提供了一些默…

怎么剪切一段音乐其中的片段

剪切音乐想必大家都不陌生&#xff0c;在各种手机铃声中我们都需要用到它来制作个性有趣的来电铃声&#xff0c;那么大家知道有什么简便的方法使用吗&#xff1f;小编有一个办法就是利用剪切工具的功能就可以完成了&#xff0c;我们就不用不用一点一点的设置音频片段了&#xf…

无需重启, 使用Xephyr调试awesome

每次改了awesome总是心里忐忑的重新启动awesome 稍有不慎就会导致awesome加载失败 而使用默认配置加载. 对于改了一大堆快捷键绑定的人来说, 默认配置简直没法用了... 有时候还会直接起不来...需要用到killall awesome才能退回到lightdm的登录界面偶然发现xephyr这个工具 可以虚…

java程序员遇到的问题_Java 程序员平时最常遇到的故障:系统OOM (一)

作为 Java 程序员而言&#xff0c;先不考虑自己系统外部依赖的缓存、消息队列、数据库等等东西挂掉&#xff0c;就我们自己系统本身而言&#xff0c;最常见的挂掉的原因是什么&#xff1f;其实就是系统OOM&#xff0c;也就是所谓的内存溢出&#xff01;什么是内存溢出&#xff…

java大文件读写操作,java nio 之MappedByteBuffer,高效文件/内存映射

http://langgufu.iteye.com/blog/2107023 java处理大文件&#xff0c;一般用BufferedReader,BufferedInputStream这类带缓冲的Io类&#xff0c;不过如果文件超大的话&#xff0c;更快的方式是采用MappedByteBuffer。 MappedByteBuffer是java nio引入的文件内存映射方案&#xf…

HTML5 Canvas编写五彩连珠(3):设计

在看了几篇Canvas相关的文章后&#xff0c;发现前两节的代码实现还是有问题&#xff0c;因为知道的少&#xff0c;所以只能在自己已知的知识上做实现。不过还好&#xff0c;这是一个发现的过程&#xff0c;也是一个纠错和完善的过程。我第一次尝试一边学习一遍写博客&#xff0…

SQL面试宝典一:

1.什么是sql Injection&#xff08;sql 注入&#xff09;&#xff1f;如何防止&#xff1f; 答&#xff1a;是一种恶意将sql代码添加到输入参数中&#xff0c;传递到sql服务器解析并执行的一种攻击手法。 防止&#xff1a;1.对用户的输入进行校验&#xff0c;可以通过正则表达…

java注解的执行顺序_深入理解Spring的@Order注解和Ordered接口

前言Spring的Order注解或者Ordered接口大家都知道是控制顺序的&#xff0c;那么它们到底是控制什么顺序的&#xff1f;是控制Bean的注入顺序&#xff0c;还是Bean的实例化顺序&#xff0c;还是Bean的执行顺序呢&#xff1f;那么我们先直接给出结论再来验证结论。结论&#xff1…

数据驱动安全需三大核心新技术

要做到数据驱动安全&#xff0c;齐向东认为需要三大核心技术。第一个核心技术是大数据采集器&#xff0c;第二个是大数据引擎&#xff0c;第三个是机器学习挖掘、重要安全问题定位准确。转载于:https://www.cnblogs.com/1992825-Amelia/p/4854220.html

[转]BI 问答

http://blog.bridata.ca/?cat16 前几天Post 了一些BI 的面试问题&#xff0c;感兴趣的人很多&#xff0c;有很多人问我答案以此来评估一下自己的知识水平。坦白地说我没有写在纸上的具体答案&#xff0c;事实上每个问题也没有具体和精确的答案&#xff0c;所谓面试就不是笔试&…

没有学不会的C++:用户自定义的隐式类型转换

C 中的类型转换包含内建类型的转换和用户自定义类型的转换&#xff0c;而这两者都又可分为隐式转换和显示转换&#xff0c;所以一共有如下四象限表格中的 A、B、C、D 四种情况 隐式转换显示转换(casting)内建类型转换 (int, float ...)AB用户自定义类型转换(类 vs 类; 类 vs 内…

python scrapy菜鸟教程_scrapy学习笔记(一)快速入门

安装ScrapyScrapy是一个高级的Python爬虫框架&#xff0c;它不仅包含了爬虫的特性&#xff0c;还可以方便的将爬虫数据保存到csv、json等文件中。首先我们安装Scrapy。pip install scrapy在Windows上安装时可能会出现错误&#xff0c;提示找不到Microsoft Visual C。这时候我们…

执行eclipse,迅速failed to create the java virtual machine。

它们必须在一排&#xff0c;否则会出现The Eclipse executable launcher was unable to locate its companion shared library的错误 打开eclipse文件夹下的eclipse.ini文件。改动–launcher.XXMaxPermSize属性&#xff0c;当中此属性有两处 -startup plugins/org.eclipse.equi…

vue打包后图片找不到情况

打包之前需要修改如下配置文件&#xff1a; 配置文件一&#xff1a;build>>>utils.js (修改publicPath:"../../" , 这样写是处理打包后找不到静态文件&#xff08;图片路径失效&#xff09;的问题) 配置文件二&#xff1a;config>>>index.js(修改a…

UBUNTU安装SSH和xrdp

一、安装SSH&#xff0c;通过PUTTY访问 命令&#xff1a;sudo apt-get install ssh 查看&#xff1a;netstat -l 二、安装xrdp&#xff0c;通过远程桌面访问 命令&#xff1a;sudo apt-get install xrdp 开启远程桌面访问权限 系统-->首选项-->remote desktop 三、去掉远…

python中opencv中inrange用法_python-opencv中的cv2.inRange函数

本次目标是将一副图像从rgb颜色空间转换到hsv颜色空间&#xff0c;颜色去除白色背景部分具体就调用了cv2的两个函数&#xff0c;一个是rgb转hsv的函数具体用法hsv cv2.cvtColor(rgb_image, cv2.COLOR_BGR2HSV)然后利用cv2.inRange函数设阈值&#xff0c;去除背景部分mask cv2…

[转]C++11 随机数学习

相对于C 11之前的随机数生成器来说&#xff0c;C11的随机数生成器是复杂了很多。这是因为相对于之前的只需srand、rand这两函数即可获取随机数来说&#xff0c;C11提供了太多的选择和东西。 随机数生成算法&#xff1a; 随机数生成算法有很多&#xff0c;C11之前的C/C只…

Linux Shell ssh登录脚本

Linux 登陆服务器敲命令太多,某时候确实不便,所以就用shell写了一个 我的blog地址: http://www.cnblogs.com/caoguo 一.说明 支持秘密和密钥两种格式用户名和密码都是写文件的,明文保存二.配置 密码文件配置:序号:IP:端口:用户:密码:说明 1:192.168.88.128:22:root:toor:虚拟机…

C# 温故而知新:Stream篇(二)

C# 温故而知新&#xff1a;Stream篇&#xff08;二&#xff09; TextReader 和StreamReader 目录&#xff1a; 为什么要介绍 TextReader&#xff1f; TextReader的常用属性和方法 TextReader 示例 从StreamReader想到多态 简单介绍下Encoding 编码 StreamReader 的定义及作用 S…

usaco Pollutant Control

第一问是求最小割。第二问求最小割中集合中边最少的集合的大小。 第三问求集合中边最少且字典序最小的边的下标。 第一问直接求最大流就能解&#xff0c;第二问将原来的边的容量都改为1&#xff0c;求出来的最大流就是元素最少的一个最小割的大小。 将容量都改为1之后&#xff…

洛谷P4705 玩游戏(生成函数+多项式运算)

题面 传送门 题解 妈呀这辣鸡题目调了我整整三天……最后发现竟然是因为分治\(NTT\)之后的多项式长度不是\(2\)的幂导致把多项式的值存下来的时候发生了一些玄学错误……玄学到了我\(WA\)的点全都是\(WA\)在\(2\)的幂次行里…… 看到这种题目二话不说先推倒 \[ \begin{aligned}…

blast程序 介绍 简介

每次找都挺麻烦&#xff0c;又记不住&#xff0c;于是抄下来&#xff1a; blastp:将待查询的蛋白质序列及其互补序列一起对蛋白质序列数据库进行查询&#xff1b;blastn:将待查询的核酸序列及其互补序列一起对核酸序列数据库进行查询&#xff1b;blastx:先将待查询的核酸序列按…

java泛型的实现和原理_java 泛型实现原理

泛型思想最早在C语言的模板(Templates)中产生&#xff0c;Java后来也借用了这种思想。虽然思想一致&#xff0c;但是他们存在着本质性的不同。C中的模板是真正意义上的泛型&#xff0c;在编译时就将不同模板类型参数编译成对应不同的目标代码&#xff0c;List和List是两种不同的…

java out of range_关于Parameter index out of range求解决办法

程序&#xff1a;提示参数越界&#xff0c;但我实在不知道我到底哪里越界了。明明该我那样写的嘛。求高手帮我看看&#xff0c;现在我是弄得我有气无力了&#xff01;要死了。在去死亡的路上等着你帮帮我&#xff01;Document : replyokCreated on : 2008-9-29, 6:05:31Autho…