springAOP详解
目录
- 静态代理
- 案例
- 动态代理
- 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来实现动态代理
- 抽象角色
//抽象角色:租房
public interface Rent {public void rent();
}
- 真实角色
//真实角色: 房东,房东要出租房子
public class Host implements Rent{public void rent() {System.out.println("房屋出租");}
}
- 代理角色
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("收中介费");}
}
- 调用
//租客
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详解相关推荐
- SpringAOP描述及实现_AspectJ详解_基于注解的AOP实现_SpringJdbcTemplate详解
AOP AOP特点: 面向切面编程, 利用AOP对业务逻辑的各个部分进行抽取公共代码, 降低耦合度, 提高代码重用性, 同时提高开发效率. 采取横向抽取, 取代传统纵向继承体系重复性代码 解决事务管理 ...
- SpringAop面向切面编程使用详解
一.AOP概述 1.1 AOP的概念 AOP(Aspect Oriented Programing)面向切面编程. 它是一种编程范式,属于软工范畴,指导开发者如何组织程序结构. 它是是通过预编译方式和 ...
- spring boot 实战 / 可执行war启动参数详解
概述 上一篇文章<spring boot 实战 / mvn spring-boot:run 参数详解>主要讲解了spring boot 项目基于maven插件启动过程中借助profil ...
- spring2.0和spring2.5及以上版本的jar包区别 spring jar 包详解
spring jar 包详解 spring.jar是包含有完整发布的单个jar包,spring.jar中包含除了 spring-mock.jar里所包含的内容外其它所有jar包的内容,因为只有在开发环 ...
- 【spring】jar包详解与模块依赖关系
以spring3.X为例 jar包详解 1. spring-core.jar:包含Spring框架基本的核心工具类,Spring其它组件要都要使用到这个包里的类,是其它组件的基本核心: 2. spri ...
- java的requestmapping_SpringMVC RequestMapping 详解
SpringMVC RequestMapping 详解 RequestMapping这个注解在SpringMVC扮演着非常重要的角色,可以说是随处可见.它的知识点很简单.今天我们就一起学习Spring ...
- Spring Boot的启动器Starter详解
Spring Boot的启动器Starter详解 作者:chszs,未经博主允许不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs Spring Boot ...
- spring-jar包详解整理
Spring各jar包详解 spring.jar 是包含有完整发布模块的单个jar 包.但是不包括mock.jar,aspects.jar, spring-portlet.jar, and sprin ...
- spring(7)---深入理解Spring核心技术——Spring中的各模块详解
深入理解Spring核心技术--Spring中的各模块详解 Spring框架的两个基本概念IOC容器和AOP,相信大家现在对Spring中的这两个部分的基本概念有了一定的认识,好了,那么今天我们就来正 ...
最新文章
- Xamarin.Android提示aapt退出,代码为255
- Git_git的诞生
- 二:Maven中pom.xml元素详解
- [Teamcenter 2007 开发系列] 整合Extjs 展现页面组件
- 【李宏毅2020 ML/DL】P83 Generative Adversarial Network | Evaluation
- 832计算机专业基础,2019年考试科目832计算机组成原理与数据结构.doc
- 创建控制文件副本出现错误ORA-00205: error in identifying control file
- Unity Android 使用UnityWebRequest Post 数据后,没有获得服务器返回的数据
- gff3转mysql_GBrowse的安装和使用
- Spring Boot Actuator 监控和管理应用程序
- 各国区号json整理
- 各代iphone尺寸_iphone 各型号设备的屏幕尺寸
- UE4开发学习笔记(双人游戏共享视角,共享相机)
- 腾讯云即时通信IM知识详解
- DOM控制video实现开始/暂停按钮思路方法
- 国外开放知识图谱_什么是开放知识,如何传播?
- Word7中尾部空格不能显示下划线的解决方法
- google adsence收款超过5w美金额度该怎么继续收款?
- HTML小黄人吃球球GO域名跳转源码
- python怎么换背景颜色_Python给照片换底色(基于opencv模块)
热门文章
- 在线ssd测试软件,速度软件:AS SSD Benchmark_固态硬盘_固态硬盘评测-中关村在线...
- 最最喜欢的韩庚……这个资料-----顶了~/(≧▽≦)/~!!!
- 杭州计算机职称考试培训,杭州全国职称英语等级考试强化培训班(综合类)
- Anima2D官方中文使用手册(对应Anima2D1.1.4)
- isee 处理图片的好工具
- 面试管:Zookeeper在项目的典型应用场景请你回答一下
- 德邦维新:如何打赢“未来之战”?
- fscanf读内容后发生错误,文件指针变成乱码(野指针)
- 什么是软件驻场开发,它的优势和不足有哪些?
- 关于Android项目中的Toast那些动画实现方式