目录

  • 静态代理
    • 案例
  • 动态代理
    • spring使用的是什么动态代理?
    • JDK动态代理与cglib动态代理的实现原来及区别
    • JDK动态代理(案例)
  • AOP
    • 什么是AOP
    • Aop在Spring中的作用
    • 使用Spring实现Aop
      • 第一种方式
      • 第二种方式
      • 第三种方式(推荐)

来源参考,b站狂神说: https://www.bilibili.com/video/BV1WE411d7Dv?spm_id_from=333.999.0.0

静态代理

为什么要学习代理模式,因为AOP的底层机制就是动态代理!我们先从静态代理聊起。

静态代理角色分析

  • 抽象角色 : 一般使用接口或者抽象类来实现
  • 真实角色 : 被代理的角色
  • 代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作 .
  • 客户 : 使用代理角色来进行一些操作 .

案例

抽象角色

//抽象角色:租房
public interface Rent {public void rent();
}

真实角色

//真实角色: 房东,房东要出租房子
public class Host implements Rent{public void rent() {System.out.println("房屋出租");}
}

代理角色

public class Proxy implements Rent {private Host host;public Proxy() { }public Proxy(Host host) {this.host = host;}//租房public void rent(){seeHouse();host.rent();fare();}//看房public void seeHouse(){System.out.println("带房客看房");}//收中介费public void fare(){System.out.println("收中介费");}
}

客户

//客户类,一般客户都会去找代理!
public class Client {public static void main(String[] args) {//房东要租房Host host = new Host();//中介帮助房东Proxy proxy = new Proxy(host);//你去找中介!proxy.rent();}
}

分析: 在这个过程中,你直接接触的就是中介,就如同现实生活中的样子,你看不到房东,但是你依旧租到了房东的房子通过代理,这就是所谓的代理模式,程序源自于生活,所以学编程的人,一般能够更加抽象的看待生活中发生的事情。

优点:

  • 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
  • 公共的业务由代理来完成 . 实现了业务的分工 ,
  • 公共业务发生扩展时变得更加集中和方便

缺点 :

  • 类多了 , 多了代理类 , 工作量变大了 . 开发效率降低 .

我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理 !

动态代理

  • 动态代理的角色和静态代理的一样 .
  • 动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
  • 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
    • 基于接口的动态代理----JDK动态代理
    • 基于类的动态代理–cglib
    • javasist 来生成动态代理 . 百度一下javasist

spring使用的是什么动态代理?

spring中使用到两种动态代理(JDK和cglib)。spring会判断目标有没有实现接口,如果有就使用jdk动态代理;没有则使用cglib动态代理。也可以通过设置,强制使用cglib动态代理。详细源码分析

JDK动态代理与cglib动态代理的实现原来及区别

原理:

  • jdk动态代理与cglib动态代理的思想都是通过字节码去生成一个类,然后对原来的类进行功能增强
  • JDK动态代理是实现InvocationHandler接口,重写invoke(),通过反射的方式去调用目标类的代码。JDK的代理是针对接口的,所以被代理的对象必须要实现接口
  • cglib实现MethodInterceptor接口,重写intercept(),对目标类生成子类覆盖他的方法,由于采用的是继承的方式,故目标类不可以被final修饰

区别:

  • jdk动态代理要求目标类必须实现接口
  • 在代理类时,jdk动态代理生成一个文件;cglib会生成三个文件,生成代理类时jdk会更快
  • jdk动态代理调用方法是通过反射,cglib是通过fastclass机制,通过枚举、索引去定位到方法。在jdk1.8之前cglib会更快,1.8之后jdk会更快

JDK动态代理(案例)

jdk与cglib动态代理的代码都大同小异,这里使用jdk来实现动态代理

  1. 抽象角色
//抽象角色:租房
public interface Rent {public void rent();
}
  1. 真实角色
//真实角色: 房东,房东要出租房子
public class Host implements Rent{public void rent() {System.out.println("房屋出租");}
}
  1. 代理角色
public class ProxyInvocationHandler implements InvocationHandler {private Rent rent;public void setRent(Rent rent) {this.rent = rent;}//生成代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色public Object getProxy(){return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);}// proxy : 代理类 method : 代理类的调用处理程序的方法对象.// 处理代理实例上的方法调用并返回结果@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {seeHouse();//核心:本质利用反射实现!Object result = method.invoke(rent, args);fare();return result;}//看房public void seeHouse(){System.out.println("带房客看房");}//收中介费public void fare(){System.out.println("收中介费");}
}
  1. 调用
//租客
public class Client {public static void main(String[] args) {//真实角色Host host = new Host();//代理实例的调用处理程序ProxyInvocationHandler pih = new ProxyInvocationHandler();pih.setRent(host); //将真实角色放置进去!Rent proxy = (Rent)pih.getProxy(); //动态生成对应的代理类!proxy.rent();}
}

核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!

AOP

什么是AOP

AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现
程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的
一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使
得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

Aop在Spring中的作用

  • 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要
  • 关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 …
  • 切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。
  • 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
  • 目标(Target):被通知对象。
  • 代理(Proxy):向目标对象应用通知之后创建的对象。
  • 切入点(PointCut):切面通知 执行的 “地点”的定义。
  • 连接点(JointPoint):与切入点匹配的执行点。

使用Spring实现Aop

导入一个依赖包

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version>
</dependency>

首先编写我们的业务接口和实现类

public interface UserService {public void add();public void delete();public void update();public void search();
}public class UserServiceImpl implements UserService{@Overridepublic void add() {System.out.println("增加用户");}@Overridepublic void delete() {System.out.println("删除用户");}@Overridepublic void update() {System.out.println("更新用户");}@Overridepublic void search() {System.out.println("查询用户");}
}

第一种方式

通过 Spring API 实现
编写增强类,一个前置增强 一个后置增强

public class Log implements MethodBeforeAdvice {//method : 要执行的目标对象的方法//objects : 被调用的方法的参数//Object : 目标对象@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {System.out.println( o.getClass().getName() + "的" + method.getName()+ "方法被执行了");}
}
public class AfterLog implements AfterReturningAdvice {//returnValue 返回值//method被调用的方法//args 被调用的方法的对象的参数//target 被调用的目标对象@Overridepublic void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {System.out.println("执行了" + target.getClass().getName()+ "的" + method.getName()+ "方法," + "返回值:"+returnValue);}
}

最后去spring的文件中注册 , 并实现aop切入实现 , 注意导入约束

<?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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--注册bean--><bean id="userService" class="com.kuang.service.UserServiceImpl"/><bean id="log" class="com.kuang.log.Log"/><bean id="afterLog" class="com.kuang.log.AfterLog"/><!--aop的配置--><aop:config><!--切入点 expression:表达式匹配要执行的方法--><aop:pointcut id="pointcut" expression="execution(*com.kuang.service.UserServiceImpl.*(..))"/><!--执行环绕; advice-ref执行方法 . pointcut-ref切入点--><aop:advisor advice-ref="log" pointcut-ref="pointcut"/><aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/></aop:config>
</beans>

第二种方式

写我们自己的一个切入类

public class DiyPointcut {public void before(){System.out.println("---------方法执行前---------");}public void after(){System.out.println("---------方法执行后---------");}
}

去spring中配置

<!--第二种方式自定义实现-->
<!--注册bean-->
<bean id="diy" class="com.kuang.config.DiyPointcut"/><!--aop的配置-->
<aop:config><!--第二种方式:使用AOP的标签实现--><aop:aspect ref="diy"><aop:pointcut id="diyPonitcut" expression="execution(*com.kuang.service.UserServiceImpl.*(..))"/><aop:before pointcut-ref="diyPonitcut" method="before"/><aop:after pointcut-ref="diyPonitcut" method="after"/></aop:aspect>
</aop:config>

第三种方式(推荐)

package com.kuang.config;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class AnnotationPointcut {@Before("execution(* com.kuang.service.UserServiceImpl.*(..))")public void before(){System.out.println("---------方法执行前---------");}@After("execution(* com.kuang.service.UserServiceImpl.*(..))")public void after(){System.out.println("---------方法执行后---------");}@Around("execution(* com.kuang.service.UserServiceImpl.*(..))")public void around(ProceedingJoinPoint jp) throws Throwable {System.out.println("环绕前");System.out.println("签名:"+jp.getSignature());//执行目标方法proceedObject proceed = jp.proceed();System.out.println("环绕后");System.out.println(proceed);}
}

注意:需要注册bean,支持注解配置

springAOP详解相关推荐

  1. SpringAOP描述及实现_AspectJ详解_基于注解的AOP实现_SpringJdbcTemplate详解

    AOP AOP特点: 面向切面编程, 利用AOP对业务逻辑的各个部分进行抽取公共代码, 降低耦合度, 提高代码重用性, 同时提高开发效率. 采取横向抽取, 取代传统纵向继承体系重复性代码 解决事务管理 ...

  2. SpringAop面向切面编程使用详解

    一.AOP概述 1.1 AOP的概念 AOP(Aspect Oriented Programing)面向切面编程. 它是一种编程范式,属于软工范畴,指导开发者如何组织程序结构. 它是是通过预编译方式和 ...

  3. spring boot 实战 / 可执行war启动参数详解

    概述   上一篇文章<spring boot 实战 / mvn spring-boot:run 参数详解>主要讲解了spring boot 项目基于maven插件启动过程中借助profil ...

  4. spring2.0和spring2.5及以上版本的jar包区别 spring jar 包详解

    spring jar 包详解 spring.jar是包含有完整发布的单个jar包,spring.jar中包含除了 spring-mock.jar里所包含的内容外其它所有jar包的内容,因为只有在开发环 ...

  5. 【spring】jar包详解与模块依赖关系

    以spring3.X为例 jar包详解 1. spring-core.jar:包含Spring框架基本的核心工具类,Spring其它组件要都要使用到这个包里的类,是其它组件的基本核心: 2. spri ...

  6. java的requestmapping_SpringMVC RequestMapping 详解

    SpringMVC RequestMapping 详解 RequestMapping这个注解在SpringMVC扮演着非常重要的角色,可以说是随处可见.它的知识点很简单.今天我们就一起学习Spring ...

  7. Spring Boot的启动器Starter详解

    Spring Boot的启动器Starter详解 作者:chszs,未经博主允许不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs Spring Boot ...

  8. spring-jar包详解整理

    Spring各jar包详解 spring.jar 是包含有完整发布模块的单个jar 包.但是不包括mock.jar,aspects.jar, spring-portlet.jar, and sprin ...

  9. spring(7)---深入理解Spring核心技术——Spring中的各模块详解

    深入理解Spring核心技术--Spring中的各模块详解 Spring框架的两个基本概念IOC容器和AOP,相信大家现在对Spring中的这两个部分的基本概念有了一定的认识,好了,那么今天我们就来正 ...

最新文章

  1. Xamarin.Android提示aapt退出,代码为255
  2. Git_git的诞生
  3. 二:Maven中pom.xml元素详解
  4. [Teamcenter 2007 开发系列] 整合Extjs 展现页面组件
  5. 【李宏毅2020 ML/DL】P83 Generative Adversarial Network | Evaluation
  6. 832计算机专业基础,2019年考试科目832计算机组成原理与数据结构.doc
  7. 创建控制文件副本出现错误ORA-00205: error in identifying control file
  8. Unity Android 使用UnityWebRequest Post 数据后,没有获得服务器返回的数据
  9. gff3转mysql_GBrowse的安装和使用
  10. Spring Boot Actuator 监控和管理应用程序
  11. 各国区号json整理
  12. 各代iphone尺寸_iphone 各型号设备的屏幕尺寸
  13. UE4开发学习笔记(双人游戏共享视角,共享相机)
  14. 腾讯云即时通信IM知识详解
  15. DOM控制video实现开始/暂停按钮思路方法
  16. 国外开放知识图谱_什么是开放知识,如何传播?
  17. Word7中尾部空格不能显示下划线的解决方法
  18. google adsence收款超过5w美金额度该怎么继续收款?
  19. HTML小黄人吃球球GO域名跳转源码
  20. python怎么换背景颜色_Python给照片换底色(基于opencv模块)

热门文章

  1. 在线ssd测试软件,速度软件:AS SSD Benchmark_固态硬盘_固态硬盘评测-中关村在线...
  2. 最最喜欢的韩庚……这个资料-----顶了~/(≧▽≦)/~!!!
  3. 杭州计算机职称考试培训,杭州全国职称英语等级考试强化培训班(综合类)
  4. Anima2D官方中文使用手册(对应Anima2D1.1.4)
  5. isee 处理图片的好工具
  6. 面试管:Zookeeper在项目的典型应用场景请你回答一下
  7. 德邦维新:如何打赢“未来之战”?
  8. fscanf读内容后发生错误,文件指针变成乱码(野指针)
  9. 什么是软件驻场开发,它的优势和不足有哪些?
  10. 关于Android项目中的Toast那些动画实现方式