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

欧洲站vat激活广东东莞今日最新消息

欧洲站vat激活,广东东莞今日最新消息,专门做加盟的网站,wordpress 门户网站Spring学习笔记11 GoF代理模式_biubiubiu0706的博客-CSDN博客 AOP(Aspect Oriented Programming):面向切面编程,面向方面编程. AOP是对OOP的补充延申.底层使用动态代理实现. Spring的AOP使用的动态代理是:JDK动态代理_CGLIB动态代理技术.Spring在这两种动态代理中灵活切换.如…

Spring学习笔记11 GoF代理模式_biubiubiu0706的博客-CSDN博客

AOP(Aspect Oriented Programming):面向切面编程,面向方面编程.

AOP是对OOP的补充延申.底层使用动态代理实现.

Spring的AOP使用的动态代理是:JDK动态代理_CGLIB动态代理技术.Spring在这两种动态代理中灵活切换.如果是代理接口,会默认使用JDK动态代理,如果要代理某个类,这个类没有实现接口,就会切换使用CGLIB.当然,也可以强制通过一些配置让Spring只使用CGLIB

日志,事务管理,安全这些交叉业务(非业务代码)都属于AOP

AOP是一种思想,JDK代理,CGLIB代理都是AOP思想的实现,Spring AOP底层用的就是JDK代理和CGLIB代理

面向切面编程的七大术语:

连接点  Joinpoint:在程序的整个执行流程中,可以织入切面的位置.方法的执行前,异常抛出之后等位置.----->我的理解连接点就是用户需要被扩展的方法,其实我们将自定义注解放到目标方法上做标识,那么该注解其实就是一个连接点 连接点描述的是位置

切入点 Pointcut:程序执行流程中,真正织入切面的方法.(一个切入点对应多个连接点).---->我的理解:用户实际扩展的方法,确定了连接点,那么该方法就是一个切入点

通知 Advice: 扩展方法的具体实现

        1.前置通知:在目标方法执行之前执行  @Before

        2.后置通知:在目标方法执行之后,返回时执行  @AfterReturning

        3.环绕通知:在目标方法执行前后,都要执行的通知 也可以控制方法是否执行  @Around

        4.异常通知:在目标方法执行之后,抛出异常时执行  @AfterThrowing

        5.最终通知:无论程序是否执行成功,都要最后执行的通知   @After

切面 Aspect:切入点+通知就是切面

织入 Weaving:把通知应用到目标对象的过程

代理对象 Proxy:一个目标对象被织入通知后产生的新对象

目标对象 Target:被织入通知的对象

切入点表达式:

概念:当程序满足切入点表达式,才能进入切面,执行通知方法

1.bean("Bean的id") 根据Bean名称 进行拦截 只能匹配一个

2.within("com.example") 包名+类名 可以使用通配符*? 能匹配多个

3.execution(返回值类型  包名.类名.方法名(参数列表))

4.annotation(包名.注解名)

使用SpringAOP

Spring对AOP的实现包括已下3种方式:

第一种方式:Spring框架结合AspectJ框架实现的AOP,基于注解方式

第二种方式:Spring框架结合AspectJ框架实现的AOP,基于XML方式

第三种方式:Spring框架自己实现的AOP,基于XML配置方式

实际开发中,都是Spring+AspectJ来实现AOP,重点第一种和第二种方式.

准备环境

新建模块spring-aspectj-xml

导入依赖

<dependencies><!--Spring依赖种包含Spring-aop依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.10</version></dependency><!--Spring aspectj依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>6.0.10</version></dependency><!--junit依赖--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency>
</dependencies>

Spring配置文件中添加context命名空间和aop命名空间

先搭个架子

配置文件    注意下  这个注释可能没写对

默认情况下,<aop:aspectj-autoproxy />会使用Spring的JDK动态代理来代理目标对象。这意味着如果你的目标对象实现了至少一个接口,Spring将会使用JDK动态代理。这种代理方式仅代理实现了接口的方法。

如果目标对象没有实现任何接口,Spring将会使用CGLIB(Code Generation Library)来创建一个子类代理。CGLIB允许代理类继承目标对象,因此可以代理非接口类型的目标对象。

<aop:aspectj-autoproxy proxy-target-class="true" />
是强制使用CGLIB代理意思

测试,当调用业务层login方法时候

业务层新增一个方法

如果我在切入点表达式中修改下

可见切入点表达式很重要

新加一个业务类

修改切入点表达式

测试

下面引入所有通知

将UserService注释掉  避免看着混乱

package com.example.aspect;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;/*** @author hrui* @date 2023/9/26 0:33*/
@Component
@Aspect//标注是一个切面
public class LogAspect {//切面//切面=切入点+通知//通知就是增强,就是具体要编写的增强代码//前置通知   方法执行之前@Before("execution(* com.example.service..*(..))")//里面要写切入点表达式 UserService里的所有方法public void 增强(){System.out.println("我是一个通知,我是一段增强代码");}//后置通知   方法执行之后返回时执行@AfterReturning("execution(* com.example.service..*(..))")public void afterAdvice(){System.out.println("方法执行之后通知");}//环绕通知 目标方法执行之前和执行之后   并且在前置通知之前  在后置通知之后@Around("execution(* com.example.service..*(..))")public Object aroundAdvice(ProceedingJoinPoint joinPoint){//注意多参情况ProceedingJoinPoint要放第一位Object result = null;try {System.out.println("执行方法前");//调用目标方法result=joinPoint.proceed();System.out.println("执行方法后");} catch (Throwable throwable) {throwable.printStackTrace();}finally {}return result;}//异常通知 发生异常之后@AfterThrowing(value = "execution(* com.example.service..*(..))",throwing = "e")//当目标方法执行时,抛出异常时,可以用AfterThrowing记录public void afterThrowingAdvice(){System.out.println("报错了我就执行了");}//最终通知asd@After("execution(* com.example.service..*(..))")public void after(){System.out.println("最后我肯定会执行");}}

当系统有多个切面时候

加个切面

可以用@Order排序   数字小在前面

测试

通用切入点

切面上的代码,每个切入点都要写切入点表达式,代码冗余

package com.example.aspect;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;/*** @author hrui* @date 2023/9/26 0:33*/
@Component
@Aspect//标注是一个切面
@Order(2)
public class LogAspect {//切面//切面=切入点+通知//通知就是增强,就是具体要编写的增强代码@Pointcut("execution(* com.example.service..*(..))")public void 通用切点(){//这个方法只是一个标记,方法名随意,方法体也不需要写任何代码}//前置通知   方法执行之前@Before("通用切点()")//里面要写切入点表达式 UserService里的所有方法public void 增强(){System.out.println("我是一个通知,我是一段增强代码");}//后置通知   方法执行之后返回时执行@AfterReturning("通用切点()")public void afterAdvice(){System.out.println("方法执行之后通知");}//环绕通知 目标方法执行之前和执行之后   并且在前置通知之前  在后置通知之后@Around("通用切点()")public Object aroundAdvice(ProceedingJoinPoint joinPoint){//注意多参情况ProceedingJoinPoint要放第一位Object result = null;try {System.out.println("执行方法前");//调用目标方法result=joinPoint.proceed();System.out.println("执行方法后");} catch (Throwable throwable) {throwable.printStackTrace();}finally {}return result;}//异常通知 发生异常之后@AfterThrowing(value = "通用切点()",throwing = "e")//当目标方法执行时,抛出异常时,可以用AfterThrowing记录public void afterThrowingAdvice(){System.out.println("报错了我就执行了");}//最终通知asd@After("通用切点()")public void after(){System.out.println("最后我肯定会执行");}}

测试

范式

package com.jt.aop;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;import java.util.Arrays;/***  AOP(面向切面编程) 主要利用**动态代理**的模式 **降低程序的耦合度,扩展业务功能方法.*** 1.AOP需要被Spring容器管理 @Component* 2.标识该类是AOP切面   @Aspect* 关于AOP名词介绍* 1).连接点: 用户可以被扩展的方法    其实我们将自定义注解放到目标方法上做标识,那么该注解其实就是个连接点* 2).切入点: 用户实际扩展的方法      确定了连接点,那么该方法也就是个切入点* 3).通知:  扩展方法的具体实现       5个通知* 4).切面: 将通知应用到切入点的过程**   通知类型(必会)* 1. before:  在目标方法执行之前执行* 2. afterReturning: 在目标方法执行之后返回时执行* 3. afterThrowing:  在目标方法执行之后,抛出异常时执行* 4. after:	无论程序是否执行成功,都要最后执行的通知* 5. around: 在目标方法执行前后 都要执行的通知(完美体现了动态代理模式)* 	功能最为强大 只有环绕通知可以控制目标方法的执行** 关于通知方法总结:* 	1.环绕通知是处理业务的首选.  可以修改程序的执行轨迹* 	2.另外的四大通知一般用来做程序的监控.(监控系统) 只做记录* @author TB* @date 2020/2/12 0:24*/
@Component
//虽然标识了该类为AOP切面 但是Spring容器默认不能识别切面注解,需要手动配置
//需要在配置类SpringConfig里加上注解@EnableAspectJAutoProxy
@Aspect
public class SpringAOP {/*** 切入点表达式* 概念:当程序满足切入点表达式,才能进入切面,执行通知方法.** 1.bean("bean的ID")  根据beanId进行拦截  只能匹配一个* 2.within("包名.类名") 可以使用通配符*?      能匹配多个.* 	粒度: 上述的切入点表达式 粒度是类级别的.  粗粒度.* 3.execution(返回值类型   包名.类名.方法名(参数列表...))* 	粒度: 控制的是方法参数级别. 所以粒度较细.   最常用的.* 4.@annotation(包名.注解名)     只拦截注解.* 	粒度: 注解是一种标记 根据规则标识某个方法/属性/类    细粒度*//*** 切入点表达式练习* within:*  1.within(com.jt.*.DeptServiceImpl)   一级包下的类*  2.within(com.jt..*.DeptServiceImpl)  ..代表多级包下的类*  3.within(com.jt..*)  包下的所有的类** execution(返回值类型 包名.类名.方法名(参数列表))*  1.execution(* com.jt..*.DeptServiceImpl.add*())*  注释: 返回值类型任意的, com.jt下的所有包中的DeptServiceImpl的类*        的add开头的方法 ,并且没有参数.**  2.execution(* com.jt..*.*(..))*  注释: 返回值类型任意,com.jt包下的所有包的所有类的所有方法 任意参数.**  3.execution(int com.jt..*.*(int))*  4.execution(Integer com.jt..*.*(Integer))*  强调: 在Spring表达式中没有自动拆装箱功能! 注意参数类型** @annotation(包名.注解名)*     @Before("@annotation(com.jt.anno.Cache)")*    只拦截特定注解的内容.*///1.定义before通知//@Before("bean(deptServiceImpl)")//扫描的是一个类 因此该类里所有方法都被扩展到了//@Before("within(com.jt.service.DeptServiceImpl)")//和上面效果一样//@Before("execution(* com.jt.service.DeptServiceImpl.add*())")//*表示返回值类型任意 add*表示以add开头的方法名 最后()表示参数是空的//@Before("@annotation(com.jt.anno.Cache)")//意思有该注解 就作为切入点   因此用注解标识最常用(自定义个注解)/*** spring为了AOP动态获取目标对象及方法中的数据,则通过Joinpoint* JoinPoint是所有通知的公共参数,无论哪种通知里都可以使用* 在Before里可以获取* 对象做数据传递获取如:* 1.获取目标对象的类型* 2.获取目标方法的名称* 3.获取目标方法的参数* @param joinPoint*/@Before("pointcut()")public void before(JoinPoint joinPoint){//前置方法一般作用获取参数,方法名,等等System.out.println("目标对象的Class类对象: "+joinPoint.getTarget().getClass());System.out.println("获取目标方法的方法签名: "+joinPoint.getSignature());System.out.println("获取目标对象的类名: "+ joinPoint.getSignature().getDeclaringTypeName());System.out.println("获取目标对象方法名: "+ joinPoint.getSignature().getName());System.out.println("获取目标方法参数: "+ Arrays.toString(joinPoint.getArgs()));System.out.println("我是before通知");}//1.定义一个切入点@Pointcut("@annotation(com.jt.anno.Cache)")public void pointcut(){}//如果每个通知前都加个切入点表达式  那么也太冗余了 因此我们可以定义个切入点 其他通知都围绕切入点//@BafterReturning("@annotation(com.jt.anno.Cache)")/*** JoinPoint参数是所有通知方法公有的*AfterReturning是目标方法返回执行之后返回时执行* 可以记录方法的返回值* AfterReturning注解里 value和pointcut是相同的效果:也就是说* @AfterReturning(value="pointcut()",returning="result")和@AfterReturning(pointcut="pointcut()",returning="result")* 效果一样* returning:将方法的返回值,通过形参result(这个随便取名)来进行传递(Spring会将返回值赋值给你定义的这个变量)*/@AfterReturning(value="pointcut()",returning="result")public void afterReturning(JoinPoint joinPoint,Object result){//这里注意 如果有需要用到JointPoint参数 那么必须放在第一个位置  不用可以去掉System.out.println("目标返回值结果是: "+result);System.out.println("我是AfterReturning的通知");}@AfterThrowing(pointcut = "pointcut()",throwing="e")//当目标方法执行时,抛出异常时,可以用AfterThrowing记录public void afterThrowing(Exception e){System.out.println("获取目标异常信息: "+e.getMessage());System.out.println("获取目标异常类型: "+e.getClass());System.out.println("我是AfterThrowing的通知,出现异常了");}@After("pointcut()")public void after(){System.out.println("我是After的通知");}/*** 关于环绕通知的说明* 作用: 可以控制目标方法是否执行.* 参数: ProceedingJoinPoint 通过proceed方法控制目标方法执行.* 注意事项:*  ProceedingJoinPoint 只能适用环绕通知* @return*/@Around("pointcut()")public Object around(ProceedingJoinPoint joinPoint){//注意多参情况ProceedingJoinPoint要放第一位Object result = null;try {System.out.println("环绕通知开始");//1.执行下一个通知  2.执行目标方法 3.接收返回值Long start = System.currentTimeMillis();result = joinPoint.proceed();Long end = System.currentTimeMillis();System.out.println("耗时:"+(end-start));} catch (Throwable throwable) {throwable.printStackTrace();}System.out.println("环绕通知结束");return result;}
}

关于全注解式开发,不用Spring配置文件

测试也需要改下

Spring AOP基于XML方式的实现

新建模块spring-aspectj-xml2

依赖

<dependencies><!--Spring依赖种包含Spring-aop依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.10</version></dependency><!--Spring aspectj依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>6.0.10</version></dependency><!--junit依赖--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency>
</dependencies>

 目标类

切面类

http://www.mmbaike.com/news/26853.html

相关文章:

  • 网站模板怎么连接域名发布外链
  • 常见的网站开发语言关键词如何确定
  • 互联网网站如何做seo按照搜索引擎的什么对网站
  • 杭州萧山网站建设公司2345网址导航桌面版
  • 网站系统维护制作网页
  • 医疗保险网站山东济南最新消息
  • 电子商务网站是什么google 网站推广
  • wordpress做专题杭州最专业的seo公司
  • 不会写程序如何做网站大型网站seo课程
  • 提供设计网站效果图爱站小工具计算器
  • 深圳做公司网站什么平台引流最快
  • 深圳企业网站建设谷歌推广外贸建站
  • 涞水网站建设站长之家域名查询排行
  • 手机网站开发视频教程电商平台排名
  • 抖音运营推广策划方案百度seo软件是做什么的
  • 东莞虎门大桥seo日常工作内容
  • b2b的两种网站类型网店代运营诈骗
  • 香港做网站什么费用百度竞价的优势和劣势
  • 网站开发从何学起重庆旅游seo整站优化
  • 网站移动端怎么做信阳百度推广公司电话
  • 网站大全免黄百度账号注册平台
  • 河北省建设厅网站备案绍兴seo优化
  • 微网站如何建设方案百度数据指数
  • 怎么自己建立一个网站后台百度账号快速注册入口
  • 嘉定网站设计制作优化排名推广优化工具
  • 郑州市疫情防控指挥部办公室搜索引擎seo优化
  • 做网站做哪个好网络营销优化
  • 网站长尾词怎么做苏州seo快速优化
  • 网站管理助手 phpmyadmin云资源软文发布平台
  • 南宁seo域名seo推广软件费用