什么是代理?

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

什么是静态代理?

  由程序创建或特定工具自动生成源代码,在程序运行前,代理类的.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. Spark如何与深度学习框架协作,处理非结构化数据

    随着大数据和AI业务的不断融合,大数据分析和处理过程中,通过深度学习技术对非结构化数据(如图片.音频.文本)进行大数据处理的业务场景越来越多.本文会介绍Spark如何与深度学习框架进行协同工作,在大数 ...

  2. 测试人员遇到Android APP崩溃和无响应手足无措?

    这2天,在测APP兼容性时,遇到APP奔溃闪退的情况.将问题反馈给开发后,开发自己调试后,没有复现.由于又是远程,base地不在一块,我总不能把手机寄过去吧,那也太费事了. 所以就想到,提供明确的报错 ...

  3. python 获取两位的月份(09)和天数(09)

  4. SpringCloud教程第4篇:Hystrix(F版本)

    在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign来调用.为了保证其高可用,单个服务 ...

  5. 黎活明8天快速掌握android视频教程--24_网络通信之网页源码查看器

    1 该项目的主要功能就是从将后台的html网页在Android的界面上显示出来 后台就是建立一个java web工程在工程尚建立一个html或者jsp文件就可以了,这里主要看Android客户端的程序 ...

  6. activiti学习笔记二

    上一篇文章大概讲了下什么是流程引擎,为什么我们要用流程引擎,他的基本原理是啥,以及怎么进行基本的使用,这篇文章我们再讲下其他的一些使用. 删除流程部署 package activiti02; impo ...

  7. SQL注入之注入点的寻找

    注入点的判断 判断一个链接是否存在注入漏洞,可以通过对其传入的参数(但不仅仅只限于参数,还有cookie注入,HTTP头注入等) 进行构造,然后对服务器返回的内容进行判断来查看是否存在注入点. 注入点 ...

  8. 在Github上建立自己的个人主页

    目录 注册Github账号 登录Github账号 建立新仓库 选择个人主页的主题 注册Github账号 首先打开Github的主页(https://github.com/),点击右上角的sign up ...

  9. LeetCode63. 不同路径 II

    这题和62题类似,只不过这里多了障碍物,只需要把有障碍物的格子的方案数设置为0即可,其他格子还是原来的走法. class Solution { public: int uniquePathsWithO ...

  10. js写一个简单的九九乘法表

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...