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 ...
随机推荐
- WebDriverWait与expected_conditions结合使用
expected_conditions判断页面元素 demo2 from selenium import webdriver from selenium.webdriver.support.ui im ...
- gradle的搭建和配置
下载 官方网站:https://gradle.org/install/#manually 提供了两种下载方式,Binary-only是只下载二进制源码,Complete, with docs and ...
- OO第一单元——谜之随性总结
前言 第一单元的作业主要是以多项式求导为载体来训练我们的面向对象的思维,难度循序渐进,复杂度也一直在提高,但是面向对象的体现性也越来越强,当然带来的优势与便利也在逐步提升.下面的内容主要从需求分析,代 ...
- 深入理解Java虚拟机学习笔记(一)-----Java内存区域
一 概述 对于 Java 程序员来说,在虚拟机自动内存管理机制下,不再需要像C/C++程序开发程序员这样为内一个 new 操作去写对应的 delete/free 操作,不容易出现内存泄漏和内存溢出问题 ...
- brother b-PAC sdk开发包
brother b-PAC sdk开发包 https://download.brother.com/welcome/dlfp100607/bsdkw32031eu.exe https://www.br ...
- vulstack红队评估(一)
一.环境搭建: 1.根据作者公开的靶机信息整理: 虚拟机初始所有统一密码:hongrisec@2019 因为登陆前要修改密码,改为了panda666... 2.虚拟网卡网络配置: ①Win7双 ...
- Beta冲刺<3/10>
这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺--第三天(05.21) 作业正文 如下 其他参考文献 ... B ...
- Python 为什么不支持 i++ 自增语法,不提供 ++ 操作符?
在 C/C++/Java 等等语言中,整型变量的自增或自减操作是标配,它们又可分为前缀操作(++i 和 --i)与后缀操作(i++ 和 i--),彼此存在着一些细微差别,各有不同的用途. 这些语言的使 ...
- 【解读】Https协议
一.为什么需要https 1.HTTP是明文传输的,也就意味着,介于发送端.接收端中间的任意节点都可以知道你们传输的内容是什么.这些节点可能是路由器.代理等. 举个最常见的例子,用户登陆.用户输入账号 ...
- python 之 数据类型初接触
python 之 数据类型初接触 标准数据类型 Python3 中有六个标准的数据类型: Number(数字) String(字符串) List(列表) Tuple(元组) Set(集合) Dicti ...