Spring AOP里的静态代理和动态代理,你真的了解嘛?
什么是代理?
为某一个对象创建一个代理对象,程序不直接用原本的对象,而是由创建的代理对象来控制原对象,通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间
什么是静态代理?
由程序创建或特定工具自动生成源代码,在程序运行前,代理类的.class文件就已经存在
通过将目标类与代理类实现同一个接口,让代理类持有真实类对象,然后在代理类方法中调用真实类方法,在调用真实类方法的前后添加我们所需要的功能扩展代码来达到增强的目的。
优点
代理使客户端不需要知道实现类是什么,怎么做,而客户端只需知道代理即可
方便增加功能,扩展业务逻辑
缺点
代理类中常出现大量冗余的代码,非常不利于扩展和维护
如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度
案例演示
PayService.java(接口)
package net.cybclass.sp.proxy;
public interface PayService {
/**
* 支付回调
* @param outTradeNo 订单号
* @return
*/
String callback(String outTradeNo);
/**
* 下单
* @param userId 用户id
* @param productId 产品id
* @return
*/
int save(int userId,int productId);
}
PayServiceImpl.java(接口实现类)
package net.cybclass.sp.proxy;
public class PayServiceImpl implements PayService{
public String callback(String outTradeNo) {
System.out.println("目标类 PayServiceImpl 回调 方法 callback");
return outTradeNo;
}
public int save(int userId, int productId) {
System.out.println("目标类 PayServiceImpl 回调 方法 save");
return productId;
}
}
StaticProxyPayServiceImpl.java(接口实现类,静态代理)
package net.cybclass.sp.proxy;
public class StaticProxyPayServiceImpl implements PayService{
private PayService payService;
public StaticProxyPayServiceImpl(PayService payService)
{
this.payService=payService;
}
public String callback(String outTradeNo) {
System.out.println("StaticProxyPayServiceImpl callback begin");
String result=payService.callback(outTradeNo);
System.out.println("StaticProxyPayServiceImpl callback end");
return result;
}
public int save(int userId, int productId) {
System.out.println("StaticProxyPayServiceImpl save begin");
int id = payService.save(userId, productId);
System.out.println("StaticProxyPayServiceImpl save end");
return id;
}
}
演示

什么是动态代理?
在程序运行时,运用反射机制动态创建而成,无需手动编写代码
- JDK动态代理
- CGLIB动态代理(原理:是对指定的业务类生成一个子类,并覆盖其中的业务方法来实现代理)
jdk动态代理演示
定义一个类,去实现InvocationHandler这个接口,并车从写invoke方法 //Object proxy:被代理的对象
//Method method:要调用的方法
//Object[] args:方法调用时所需要参数
public Object invoke(Object proxy, Method method, Object[] args){}
PayService.java(接口)
package net.cybclass.sp.proxy;
public interface PayService {
/**
* 支付回调
* @param outTradeNo 订单号
* @return
*/
String callback(String outTradeNo);
/**
* 下单
* @param userId 用户id
* @param productId 产品id
* @return
*/
int save(int userId,int productId);
}
PayServiceImpl.java(接口实现类)
package net.cybclass.sp.proxy;
public class PayServiceImpl implements PayService{
public String callback(String outTradeNo) {
System.out.println("目标类 PayServiceImpl 回调 方法 callback");
return outTradeNo;
}
public int save(int userId, int productId) {
System.out.println("目标类 PayServiceImpl 回调 方法 save");
return productId;
}
}
JDKProxy.java(jdk动态代理类)
package net.cybclass.sp.proxy; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class JDKProxy implements InvocationHandler {
//目标类
private Object targetObject; /**
* 获取代理对象
* @param targetObject 目标类
* @return
*/
public Object newProxyInstance(Object targetObject) {
this.targetObject = targetObject;
//绑定关系,也就是和具体的那个实现类关联
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this);
} /**
* JDK动态代理
*
* @param proxy 静态代理对象
* @param method 要调用的方法
* @param args 方法调用时所需要参数
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try {
System.out.println("通过JDK动态代理调用"+method.getName()+",打印日志 begin");
result = method.invoke(targetObject, args);
System.out.println("通过JDK动态代理调用"+method.getName()+",打印日志 end");
} catch (Exception ex) {
ex.printStackTrace();
}
return result;
}
}
演示

CGLIB动态代理演示
PayService.java(接口)
package net.cybclass.sp.proxy;
public interface PayService {
/**
* 支付回调
* @param outTradeNo 订单号
* @return
*/
String callback(String outTradeNo);
/**
* 下单
* @param userId 用户id
* @param productId 产品id
* @return
*/
int save(int userId,int productId);
}
PayServiceImpl.java(接口实现类)
package net.cybclass.sp.proxy;
public class PayServiceImpl implements PayService{
public String callback(String outTradeNo) {
System.out.println("目标类 PayServiceImpl 回调 方法 callback");
return outTradeNo;
}
public int save(int userId, int productId) {
System.out.println("目标类 PayServiceImpl 回调 方法 save");
return productId;
}
}
CGLIBProxy.java(CGLIB动态代理类)
package net.cybclass.sp.proxy; import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CGLIBProxy implements MethodInterceptor {
//目标类
private Object targetObject;
//绑定关系
public Object newProxyInstance(Object targetObject){
this.targetObject=targetObject;
Enhancer enhancer=new Enhancer();
//设置代理类的父类(目标类)
enhancer.setSuperclass(this.targetObject.getClass());
//设置回调函数
enhancer.setCallback(this);
//创建子类(代理对象)
return enhancer.create();
}
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object result=null;
try
{
System.out.println("通过CGLIB动态代理调用"+method.getName()+",打印日志 begin");
result=methodProxy.invokeSuper(o,args);
System.out.println("通过CGLIB动态代理调用"+method.getName()+",打印日志 end");
}
catch (Exception ex){
ex.printStackTrace();
}
return result;
}
}
演示

Spring AOP里的静态代理和动态代理,你真的了解嘛?的更多相关文章
- Spring AOP中的JDK和CGLib动态代理哪个效率更高?
一.背景 今天有小伙伴面试的时候被问到:Spring AOP中JDK 和 CGLib动态代理哪个效率更高? 二.基本概念 首先,我们知道Spring AOP的底层实现有两种方式:一种是JDK动态代理, ...
- Spring AOP简介与底层实现机制——动态代理
AOP简介 AOP (Aspect Oriented Programing) 称为:面向切面编程,它是一种编程思想.AOP 是 OOP(面向对象编程 Object Oriented Programmi ...
- Spring AOP 5种通知与java动态代理
接口,要求为每个方法前后添加日志 @Component("arithmeticCalculator") public class ArithmeticCalculatorImpl ...
- Spring AOP中的JDK和CGLIB动态代理
Spring在将Advice织入目标对象的Joinpoint是在运行时动态进行的.它采用的方式可能有两种,即JDK动态代理与CGLIB代理.Spring会根据具体的情况在两者之间切换. 实际情况如下: ...
- java面试题之spring aop中jdk和cglib哪个动态代理的性能更好?
在jdk6和jdk7的时候,jdk比cglib要慢: 在jdk8的时候,jdk性能得到提升比cglib要快很多: 结论出自:https://www.cnblogs.com/xuliugen/p/104 ...
- Java:静态代理 and 动态代理
代理模式是常用的设计模式,其特征是代理类与委托类具有相同的接口,在具体实现上,有静态代理和动态代理之分.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并 ...
- java:struts框架2(方法的动态和静态调用,获取Servlet API三种方式(推荐IOC(控制反转)),拦截器,静态代理和动态代理(Spring AOP))
1.方法的静态和动态调用: struts.xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCT ...
- java中代理,静态代理,动态代理以及spring aop代理方式,实现原理统一汇总
若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. ...
- spring——AOP(静态代理、动态代理、AOP)
一.代理模式 代理模式的分类: 静态代理 动态代理 从租房子开始讲起:中介与房东有同一的目标在于租房 1.静态代理 静态代理角色分析: 抽象角色:一般使用接口或者抽象类来实现(这里为租房接口) pub ...
随机推荐
- 《ElasticSearch入门》一篇管够,持续更新
一.顾名思义: Elastic:灵活的:Search:搜索引擎 二.官方简介: Elasticsearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTf ...
- 8种排序算法 Java实现
冒泡排序 O(n2) 两个数比较大小,较大的数下沉,较小的数冒起来. public static void bubbleSort(int[] a) { //临时变量 int temp; //i是循环次 ...
- Android学习笔记上下文菜单
布局文件main_activity.xml <?xml version="1.0" encoding="utf-8"?> <RelativeL ...
- Linux 虚拟机详细安装MySQL
准备工作 下载MySQL 去官网下载MySQL:点我直达 百度云盘地址:链接: https://pan.baidu.com/s/1qBN4r6t8gvq-I4CFfQQ-EA 密码: hei3 检查L ...
- c++ cc24a_demo //转换函数,用来做转换操作符,int()括号里面必须是空的,必须定义为const,代码示范
c++ cc24a_demo //转换函数,用来做转换操作符,int()括号里面必须是空的,必须定义为const,代码示范 #include <iostream> #include < ...
- <用户输入url按下回车,一直到用户看到界面,这期间经历了什么>
用户输入url按下回车,一直到用户看到界面,这期间都经历什么? 一. DNS解析缓存: 1. 找到浏览器缓存解析域名: 2. 找到和 DNS 缓存 ; 3. 找到路由器 DNS 缓存: 4. 找到查 ...
- 在ASP.NET 中有哪些数据验证控件(请解释ASP.NET中以什么方式进行数据验证)?
(1)RequiredFieldValidator:检查用户是否输入: (2)CompareValidator:检查两个表单输入项的输入信息是否存在某种指定关系,比如大.等于等: (3)RangeVa ...
- 前端开发神器Charles从入门到卸载
前言 本文将带大家学习使用前端开发神器-charles,从基本的下载安装到常见配置使用,为大家一一讲解. 一.花式夸奖Charles 截取 Http 和 Https 网络封包. 支持重发网络请求,方便 ...
- cv2.VideoCapture 图像旋转问题
使用cv2.VideoCapture()时发现,分解后的图片均顺时针旋转90度, 为了重新转回来使用np.rot90(mat, 1)即逆时针将矩阵旋转90度. 大功告成!!!
- electron打造桌面应用
Electron 将网页打包成桌面应用(web页面生成exe) http://m.blog.csdn.net/u014563989/article/details/75045052 Electron学 ...