什么是代理?

  为某一个对象创建一个代理对象,程序不直接用原本的对象,而是由创建的代理对象来控制原对象,通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间

什么是静态代理?

  由程序创建或特定工具自动生成源代码,在程序运行前,代理类的.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里的静态代理和动态代理,你真的了解嘛?的更多相关文章

  1. Spring AOP中的JDK和CGLib动态代理哪个效率更高?

    一.背景 今天有小伙伴面试的时候被问到:Spring AOP中JDK 和 CGLib动态代理哪个效率更高? 二.基本概念 首先,我们知道Spring AOP的底层实现有两种方式:一种是JDK动态代理, ...

  2. Spring AOP简介与底层实现机制——动态代理

    AOP简介 AOP (Aspect Oriented Programing) 称为:面向切面编程,它是一种编程思想.AOP 是 OOP(面向对象编程 Object Oriented Programmi ...

  3. Spring AOP 5种通知与java动态代理

    接口,要求为每个方法前后添加日志  @Component("arithmeticCalculator") public class ArithmeticCalculatorImpl ...

  4. Spring AOP中的JDK和CGLIB动态代理

    Spring在将Advice织入目标对象的Joinpoint是在运行时动态进行的.它采用的方式可能有两种,即JDK动态代理与CGLIB代理.Spring会根据具体的情况在两者之间切换. 实际情况如下: ...

  5. java面试题之spring aop中jdk和cglib哪个动态代理的性能更好?

    在jdk6和jdk7的时候,jdk比cglib要慢: 在jdk8的时候,jdk性能得到提升比cglib要快很多: 结论出自:https://www.cnblogs.com/xuliugen/p/104 ...

  6. Java:静态代理 and 动态代理

    代理模式是常用的设计模式,其特征是代理类与委托类具有相同的接口,在具体实现上,有静态代理和动态代理之分.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并 ...

  7. java:struts框架2(方法的动态和静态调用,获取Servlet API三种方式(推荐IOC(控制反转)),拦截器,静态代理和动态代理(Spring AOP))

    1.方法的静态和动态调用: struts.xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCT ...

  8. java中代理,静态代理,动态代理以及spring aop代理方式,实现原理统一汇总

    若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. ...

  9. spring——AOP(静态代理、动态代理、AOP)

    一.代理模式 代理模式的分类: 静态代理 动态代理 从租房子开始讲起:中介与房东有同一的目标在于租房 1.静态代理 静态代理角色分析: 抽象角色:一般使用接口或者抽象类来实现(这里为租房接口) pub ...

随机推荐

  1. 使用LaTeX输入矩阵

    当前各种文本编辑器支持的LaTeX数学公式库大多基于KaTeX,或者在Web中用MathJax的比较多,下面给出一种在Web中输入矩阵的例子 $$\left[ \begin{array}{cccc}a ...

  2. 利用Azure Functions和k8s构建Serverless计算平台

    题记:昨晚在一个技术社区直播分享了"利用Azure Functions和k8s构建Serverless计算平台"这一话题.整个分享分为4个部分:Serverless概念的介绍.Az ...

  3. 事务的特性ACID、隔离级别

    1.事务特性ACID 1.1 事务的四大特性 1.原子性(Atomicity) 事务包装的一组sql,要么都执行成功,要么都失败.这些操作是不可分割的. 2.一致性(Consistency) 数据库的 ...

  4. C常见错误小记(未完)

    1.指针与NULL 下面这段代码会报错: { int *a = NULL; *a = ; printf("%d",*a); } 指针初始化为NULL,还是没有分配内存,所以会报错. ...

  5. 关于安装Django包的问题

    在Windows的环境下,有些包确实不好安装的,比如reportlab-3.2.0-cp27-none-win32.whl,根据xadmin安装的经验,从这个.whl里把文件夹reportlab解压出 ...

  6. Java基本数据类型和包装类

    一:八大基本类型 二:基本数据类型及包装类 三:基本类型和包装类的区别 1:定义不同.封装类是对象:基本类型不是. 2:使用方式不同.包装类需要先new初始化,再通过JVM根据具体情况实例化后赋值:基 ...

  7. loadRunnner中90%的响应时间

    参考博客https://blog.csdn.net/lengyue_112/article/details/1095320?utm_source=blogxgwz4 LR在场景执行完了会出个报告,其中 ...

  8. java scoket aIO 通信

    AsynchronousServerSocketChannel assc.accept(this, new ServerCompletionHandler()); 第一个参数是服务器的处理类,第二个参 ...

  9. 01[了解] Dubbo

    什么是Dubbo? 概述 Dubbo是阿里巴巴内部使用的分布式业务框架,2012年由阿里巴巴开源. 由于Dubbo在阿里内部经过广泛的业务验证,在很短时间内,Dubbo就被许多互联网公司所采用,并产生 ...

  10. ftp的passive模式

    ftp的passive模式 今天在一台测试服务器上搭建ftp,折腾了许久. 主要是不了解ftp的passive模式和port模式的区别.这里记录一下. 和passive模式对应的叫做port模式,也叫 ...