什么是代理?

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

什么是静态代理?

  由程序创建或特定工具自动生成源代码,在程序运行前,代理类的.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. ZWave 中的消息队列机制

    文章主题   在我们的日常编程中,对消息队列的需求非常常见,使用一个简洁.高效的消息队列编程模型,对于代码逻辑的清晰性,对于事件处理的高效率来说,是非常重要的.这篇文章就来看看 ZWave 中是通过什 ...

  2. Python SimpleHTTPServer (python3 -m http.server 6789)

    搭建FTP,或者是搭建网络文件系统,这些方法都能够实现Linux的目录共享.但是FTP和网络文件系统的功能都过于强大,因此它们都有一些不够方便的地方.比如你想快速共享Linux系统的某个目录给整个项目 ...

  3. 笨办法学python - 专业程序员的养成完整版PDF免费下载_百度云盘

    笨办法学python - 专业程序员的养成完整版PDF免费下载_百度云盘 提取码:xaln  怎样阅读本书 由于本书结构独特,你必须在学习时遵守几条规则 录入所有代码,禁止复制粘贴 一字不差地录入代码 ...

  4. 键盘侠Linux干货| 使用SSH方式推送文件至github仓库

    前言 作为一名优秀的计算机从业人员,相信大家github应该都知道吧.(优秀的代码托管工具) 但是由于平常使用的https方式克隆的本地仓库,每次git push时都需要输入帐号密码才能将我们修改的文 ...

  5. python 函数式编程 高阶函数 装饰器

    # -*- coding:gb2312 -*- #coding=utf-8 # 高阶函数 import math def is_sqr(x): y = int(math.sqrt(x)) return ...

  6. hexo搭建个人博客部署到个人服务器(git+nginx+hexo+next)

    本次以阿里云服务器为例,详细讲解步骤: 一.本地环境[客户端] 这里以本地的win10电脑为例 1.下载node, 默认安装,安装完成之后,node -v看看版本号 node下载 2.安装node(傻 ...

  7. C++ 公有继承、保护继承和私有继承的对比

    在c++的继承控制中,有三种不同的控制权限,分别是public.protected和private.定义派生类时,若不显示加上这三个关键字,就会使用默认的方式,用struct定义的类是默认public ...

  8. springboot集成jpa操作mybatis数据库

    数据库如下 CREATE TABLE `jpa`.`Untitled` ( `cust_id` bigint() NOT NULL AUTO_INCREMENT, `cust_address` var ...

  9. python的一些基础知识

    一.函数介绍 二.模块与包 三.面向对象介绍 四.网络编程基础应用了解 五.基于MySQL对数据库的理解及基础操作 六.粗浅学习的前端知识整理

  10. 一条update SQL语句是如何执行的

    一条更新语句的执行过程和查询语句类似,更新的流程涉及两个日志:redo log(重做日志)和binlog(归档日志).比如我们要将ID(主键)=2这一行的值加(c:字段)1,SQL语句如下: upda ...