代理定义:
代理(Proxy):是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象。
好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。

动态代理+静态代理+cglib代理 区别:

1、静态代理===>>>代理对象与目标对象要实现相同的接口或者是继承相同父类, 然后通过调用相同的方法来调用目标对象的方法

2、动态代理===>>>代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理。

3、cglib代理===>>>目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现的Cglib代理。

静态代理总结:
1.优点:可以做到在不修改目标对象的功能前提下,对目标功能扩展。
2.缺点 :因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护。

动态代理总结:
1.优点:代理对象,不需要实现接口,也叫做:JDK代理,接口代理。
2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)。

cglib代理总结:
1.优点:Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.
2.缺点:Cglib原理是针对目标类生成一个子类,覆盖其中的所有方法,所以目标类和方法不能声明为final类型。

下面上代码:

(一)动态代理:

package com.example.demo.test.dynamic.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import lombok.Data; /**
* 创建动态代理对象
* 动态代理不需要实现接口,但是需要指定接口类型
*/
public class ProxyFactory { //维护一个目标对象
private Object target; public ProxyFactory(Object target) {
this.target = target;
} //给目标对象生成代理对象
public Object getProxyInstance() { System.out.println("==>>开始代理事务");
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(target, args);
}
}
);
} }
package com.example.demo.test.dynamic.proxy;

public interface IUserDao {

    void save();

    void delete();

    void saveAndDelete();
}
package com.example.demo.test.dynamic.proxy;

public class UserDao implements IUserDao {

    public void save() {
System.out.println("====save");
} public void delete() {
System.out.println("====delete");
} public void saveAndDelete() {
save();
delete();
} }

===>>>测试:

package com.example.demo.test.dynamic.proxy;

/**
* @date: 2020/12/11 19:55
* @description:
*/
public class Client { public static void main(String[] args) {
// 目标对象
UserDao target = new UserDao();
// class aop.UserDao
System.out.println(target.getClass()); // 给目标对象,创建代理对象
IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
// class $Proxy0 内存中动态生成的代理对象
System.out.println(proxy.getClass());
System.out.println("=========================");
proxy.save();
proxy.delete();
proxy.saveAndDelete();
}
}

(一)静态代理:

package com.example.demo.test.proxy;

/**
* 代理对象,静态代理
*/
public class UserDaoProxy implements IUserDao{ //接收保存目标对象
private IUserDao target; public UserDaoProxy(IUserDao target) {
this.target = target;
} public void save() {
System.out.println("开始代理...");
target.save();
}
}
package com.example.demo.test.proxy;

/**
* 接口
*/
public interface IUserDao { void save();
}
package com.example.demo.test.proxy;

/**
* 接口实现 目标对象
*/
public class UserDao implements IUserDao { public void save() {
System.out.println("----已经保存数据!----");
} }

===>>>测试:

package com.example.demo.test.proxy;

/**
* 测试类
*/
public class AppTest { public static void main(String[] args) {
//目标对象
UserDao target = new UserDao(); //代理对象,把目标对象传给代理对象,建立代理关系
UserDaoProxy proxy = new UserDaoProxy(target); proxy.save();//执行的是代理的方法
}
}

(一)cglib代理:

package com.example.demo.test.cglib;

import com.example.demo.test.dynamic.proxy.UserDao;
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer; /**
* @date: 2020/12/11 20:07
* @description:
*/
public class CglibClient { public static void main(String[] args) { CglibProxyFactory cglibProxy = new CglibProxyFactory();
//jdk需要提供接口,cglib需要是非私有类,且不能处理final关键字修饰的方法
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(UserDao.class);
//设置回调对象
enhancer.setCallback(cglibProxy); UserDao proxy = (UserDao) enhancer.create();
proxy.save();
proxy.delete();
proxy.saveAndDelete();
}
}
package com.example.demo.test.cglib;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /**
* @author: 乔利强
* @date: 2020/12/11 20:05
* @description:
*/
public class CglibProxyFactory implements MethodInterceptor { public CglibProxyFactory() {
} /**
* 1、代理对象;2、委托类方法;3、方法参数;4、代理方法的MethodProxy对象。
*
* @param obj
* @param method
* @param objects
* @param methodProxy
* @throws Throwable
*/
@Override
public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("走代理方法......" + method.getName());
return methodProxy.invokeSuper(obj, objects);
}
}

动态代理+静态代理+cglib代理 详解的更多相关文章

  1. 静态代理和动态代理(jdk/cglib)详解

    1.静态代理模式 代理模式上,基本上有Subject角色,RealSubject角色,Proxy角色.其中:Subject角色负责定义RealSubject和Proxy角色应该实现的接口:RealSu ...

  2. 大厂高级工程师面试必问系列:Java动态代理机制和实现原理详解

    代理模式 Java动态代理运用了设计模式中常用的代理模式 代理模式: 目的就是为其他对象提供一个代理用来控制对某个真实对象的访问 代理类的作用: 为委托类预处理消息 过滤消息并转发消息 进行消息被委托 ...

  3. [转]反向代理过程与Nginx特点详解

    原文链接:<Nginx搭建反向代理服务器过程详解> 1.1 反向代理初印象 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内 ...

  4. Nginx代理功能与负载均衡详解

    序言 Nginx的代理功能与负载均衡功能是最常被用到的,关于nginx的基本语法常识与配置已在上篇文章中有说明,这篇就开门见山,先描述一些关于代理功能的配置,再说明负载均衡详细. Nginx代理服务的 ...

  5. nginx入门与实战 安装 启动 配置nginx Nginx状态信息(status)配置 正向代理 反向代理 nginx语法之location详解

    nginx入门与实战 网站服务 想必我们大多数人都是通过访问网站而开始接触互联网的吧.我们平时访问的网站服务 就是 Web 网络服务,一般是指允许用户通过浏览器访问到互联网中各种资源的服务. Web ...

  6. CentOS 7 配置 Nginx 正向代理 http、https 最详解

    手头项目中有使用到 nginx,因为使用的三方云服务器,想上外网需要购买外网IP的,可是有些需要用到外网却不常用的主机也挂个外网IP有点浪费了,便想使用nginx的反向代理来实现多台内网服务器使用一台 ...

  7. Java代理模式之Cglib代理

    Cglib代理,也叫做子类代理.在内存中构建一个子类对象从而实现对目标对象功能的扩展. CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类.不鼓励直接使用ASM,因 ...

  8. 代理模式之Cglib代理

    Cglib代理,也叫做子类代理.在内存中构建一个子类对象从而实现对目标对象功能的扩展. l  JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口.如果想代理没有实现接口的类,就可 ...

  9. Android 通过Java代码生成创建界面。动态生成View,动态设置View属性。addRules详解

    废话不多说,本文将会层层深入给大家讲解如何动态的生成一个完整的界面. 本文内容: Java代码中动态生成View Java代码中动态设置View的位置,以及其他的属性 LayoutParams详解 一 ...

  10. Struts2-整理笔记(二)常量配置、动态方法调用、Action类详解

    1.修改struts2常量配置(3种) 第一种 在str/struts.xml中添加constant标签 <struts> <!-- 如果使用使用动态方法调用和include冲突 - ...

随机推荐

  1. 微信小程序--投票小程序设计与实现(图片、视频发布、分组、审核、排名)

    投票微信小程序设计与实现(图片.视频发布.分组.审核.排名) ​ 之前接到一个需求,设计一个类似H5 投票系统之类的小程序,我绞尽脑汁,冥思苦想,最后终于做了出来. 再次感谢 @文晓港 的ColorU ...

  2. 中移动ipv6-老毛子固件获取ipv6设置

    对于有ipv6的服务商原理上可以参照下图

  3. 杭电OJ2005---第几天?(c++)

    Problem Description 给定一个日期,输出这个日期是该年的第几天. Input 输入数据有多组,每组占一行,数据格式为YYYY/MM/DD组成,具体参见sample input ,另外 ...

  4. TeamView WaitforConnectFailed错误原因

    更新到最新版本并重启如下服务 检查TCP IPV4是否选中

  5. C语言指针的大小

    C语言指针的大小 今天看到一道题目是这样的,写出以下变量在32位设备上的大小(占多少个字节) 然后其中就有一些指针类型的数据,那么我们知道在C语言中指针的大小都是一样的,不管是有数据类型的还是void ...

  6. Jenkins Android APP 持续集成体系建设二—自动部署、执行测试任务,关联打包任务

    经过上一遍博客我们知道了怎么使用Jenkins自动打包,但打完包之后,我们还需要对新包进行回归测试,确定新包有没有问题,然后才能发布包,那么,话不多说,我们先来新建个自动化回归测试任务 新包自动化回归 ...

  7. Java基础学习总结笔记

    Java基础 Java常用内存区域 栈内存空间:存储引用堆内存空间的地址 堆内存空间:保存每个对象的具体属性内容 全局数据区:保存static类型的属性 全局代码区:保存所有的方法定义 修饰符 权限修 ...

  8. Kafka底层原理剖析(近万字建议收藏)

    Kafka 简介 Apache Kafka 是一个分布式发布-订阅消息系统.是大数据领域消息队列中唯一的王者.最初由 linkedin 公司使用 scala 语言开发,在2010年贡献给了Apache ...

  9. 【MySQL】使用MySQL(连接、选择数据库、显示数据库和表信息)

    第3章 使用MySQL 文章目录 第3章 使用MySQL 连接 选择数据库 了解数据库和表 小结 简单记录 - MySQL必知必会 - [英]Ben Forta 将学习如何连接和登录到MySQL,如何 ...

  10. Java编译期注解处理器详细使用方法

    目录 Java编译期注解处理器 启用注解处理器 遍历语法树 语法树中的源节点 语法树节点的操作 给类增加注解 给类增加import语句 构建一个内部类 使用方法 chainDots方法 总结 Java ...