java代理(静态代理和jdk动态代理以及cglib代理)
版权声明:本文为Fighter168原创文章,未经允许不得转载。
说到代理,脑袋中浮现一大堆代理相关的名词,代理模式,静态代理,jdk代理,cglib代理等等。
记忆特别深刻的是,一次面试中,一位面试官问我,spring的AOP核心采用的设计模式是什么什么模式,阅读过24种设计模式,以及阅读过spring源代码的我竟然答错了,回想起来,真是日了狗了,学过那么多遍的东西都忘记了,结果是装逼失败,自己要狠下心来,把代理都搞懂!
代理模式简述
代理模式是常用的Java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
静态代理
由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。下面通过例子展示。
定义接口
- /**
- * 定义一个账户接口
- *
- * @author Fighter
- * @date 2016-04-20
- *
- */
- public interface Count {
- // 查看账户方法
- public void queryCount();
- // 修改账户方法
- public void updateCount();
- }
实现接口
- /**
- * 委托类(包含业务逻辑)
- *
- * @author Fighter
- * @date 2016-04-20
- *
- */
- public class CountImpl implements Count {
- @Override
- public void queryCount() {
- System.out.println("查看账户方法...");
- }
- @Override
- public void updateCount() {
- System.out.println("修改账户方法...");
- }
- }
添加代理
- /**
- * 这是一个代理类(增强CountImpl实现类)
- *
- * @author Fighter
- * @date 2016-04-20
- *
- */
- public class CountProxy implements Count {
- private CountImpl countImpl;
- /**
- * 覆盖默认构造器
- *
- * @param countImpl
- */
- public CountProxy(CountImpl countImpl) {
- this.countImpl = countImpl;
- }
- @Override
- public void queryCount() {
- System.out.println("事务处理之前");
- // 调用委托类的方法;
- countImpl.queryCount();
- System.out.println("事务处理之后");
- }
- @Override
- public void updateCount() {
- System.out.println("事务处理之前");
- // 调用委托类的方法;
- countImpl.updateCount();
- System.out.println("事务处理之后");
- }
- }
测试
- /**
- *测试Count类
- *
- * @author Fighter
- * @date 2016-04-20
- *
- */
- public class TestCount {
- public static void main(String[] args) {
- CountImpl countImpl = new CountImpl();
- CountProxy countProxy = new CountProxy(countImpl);
- countProxy.updateCount();
- countProxy.queryCount();
- }
- }
JDK动态代理
特点:只能对实现了接口的类生产代理,不能针对类
定义接口
- /**
- * 创建业务接口,包含业务可以提供对外的接口
- *
- * @author Fighter
- * @date 2016-04-19
- *
- */
- public interface UserService{
- /**
- * 目标方法
- */
- public void add();
- }
定义实现类
- /**
- * 创建业务接口实现类
- *
- * @author Fighter
- * @date 2016-04-19
- *
- */
- public class UserServiceImpl implements UserService{
- @Override
- public void add() {
- System.out.println("----------add----------");
- }
- }
定义代理
- /**
- * 自定义简单的Invocation,对接口提供的方法进行增强
- *
- * @author Fighter
- * @date 2016-04-19
- */
- public class MyInvocationHandler implements InvocationHandler {
- //目标对象
- private Object target;
- /**
- * 构造方法
- * @param target 目标对象
- */
- public MyInvocationHandler(Object target) {
- super();
- this.target=target;
- }
- <span style="white-space:pre"> </span>/**
- * 执行目标对象的方法
- */
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- //在目标方法执行前简单打印一下
- System.out.println("----------before----------");
- //执行目标方法对象
- Object result=method.invoke(target, args);
- //在目标方法执行之后简单打印一下
- System.out.println("----------after----------");
- return result;
- }
- /**
- * 获取目标对象的代理对象
- * @return 代理对象
- */
- public Object getProxy(){
- return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
- this.target.getClass().getInterfaces(),this);
- }
- }
jdk动态代理测试
- public class ProxyTest{
- @Test
- public void testProxy() throws Throwable{
- //实例化目标对象
- UserService userService=new UserServiceImpl();
- //实例化Invocation
- MyInvocationHandler invocationHandler=new MyInvocationHandler(userService);
- //根据目标生成代理对象
- UserService proxy=(UserService)invocationHandler.getProxy();
- //调用代理对象方法
- proxy.add();
- }
- }
CGLIB动态代理示例
CGLIB是一个强大的高性能的代码生成包。被广泛的许多AOP框架使用,如Spring的AOP和dynaop,为他们提供方法的interceptor(拦截),最流行的是OR Mapping工具hibernate也是使用CGLIB来代理单端的single-ended(多对一和一对一)关联(对集合的延迟抓取是采用其他机制实现)。EsayMock和jMock是通过模仿(moke)对象来测试java代码的包。他们都是通过使用CGLIB来为那些没有接口的类创建模仿(moke)对象。
我们先通过demo来快速了解CGLIB的使用示例。
定义实现类
- /**
- * 这个是没有实现接口的实现类
- *
- * @author student
- *
- */
- public class BookFacadeImpl {
- public void addBook() {
- System.out.println("增加图书的普通方法...");
- }
- }
定义代理
- /**
- * 使用cglib动态代理
- *
- * @author student
- *
- */
- public class BookFacadeCglib implements MethodInterceptor {
- private Object target;
- /**
- * 创建代理对象
- *
- * @param target
- * @return
- */
- public Object getInstance(Object target) {
- this.target = target;
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(this.target.getClass());
- // 回调方法
- enhancer.setCallback(this);
- // 创建代理对象
- return enhancer.create();
- }
- @Override
- // 回调方法
- public Object intercept(Object obj, Method method, Object[] args,
- MethodProxy proxy) throws Throwable {
- System.out.println("事物开始");
- proxy.invokeSuper(obj, args);
- System.out.println("事物结束");
- return null;
- }
- }
编写Cglib测试
- public class TestCglib {
- public static void main(String[] args) {
- BookFacadeCglib cglib=new BookFacadeCglib();
- BookFacadeImpl bookCglib=(BookFacadeImpl)cglib.getInstance(new BookFacadeImpl());
- bookCglib.addBook();
- }
- }
总结
AOP的核心设计模式。
java代理(静态代理和jdk动态代理以及cglib代理)的更多相关文章
- java静态代理和JDK动态代理
静态代理 编译阶段就生产了对应的代理类 public interface IBussiness { void execute(); } public class BussinessImpl imple ...
- 静态代理和jdk动态代理
要说动态代理,必须先聊聊静态代理. 静态代理 假设现在项目经理有一个需求:在项目现有所有类的方法前后打印日志. 你如何在不修改已有代码的前提下,完成这个需求? 我首先想到的是静态代理.具体做法是: 1 ...
- Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景
我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...
- 设计模式——代理模式(静态代理和JDK、CGLib动态代理)
简介 什么是代理模式? 代理模式就是多一个代理类出来,代替原对象进行一些操作.比如说租房的中介.打官司的律师.旅行社,他们可以代替我们做一些事情,这就是代理. 代理模式的应用场景: 如果已有的方法在使 ...
- AOP的底层实现-CGLIB动态代理和JDK动态代理
AOP是目前Spring框架中的核心之一,在应用中具有非常重要的作用,也是Spring其他组件的基础.它是一种面向切面编程的思想.关于AOP的基础知识,相信多数童鞋都已经了如指掌,我们就略过这部分,来 ...
- Java动态代理(二)——jdk动态代理
一.什么是动态代理?代理类在程序运行时创建的代理方式被成为动态代理.动态代理的代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的.相比于静态代理, 动态代理的 ...
- Java基础之反射生成JDK动态代理
在Java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口.通过这个类和接口可以生成JDK动态代理类或动态代理对象. JDK动态代理例子: / ...
- java学习笔记(中级篇)—JDK动态代理
一.什么是代理模式 相信大家都知道代理商这个概念,在商业中,代理商无处不在.假设你要去买东西,你不可能去找真正的厂家去买,也不可能直接跟厂家提出需求,代理商就是这中间的一桥梁,连接买家和厂商.你要买或 ...
- Spring学习之设计模式,动态代理和gclib动态代理
传统的代理模式是静态代理,也就是在方法区域中写入方法. 而动态代理的作用是,不修改实现类的代码,能够在代码的前后或者抛出异常的前后执行某个方法. 动态代理类的实现 //Interface public ...
随机推荐
- 5、pgpool-II高可用性(一)数据库的高可用性
官网示例 一.实现原理 使用 pgpool-II 软件:我们常用来实现流复制的高可用性:备库只读的,不可写:就是当主库出现问题时:需要把备库自动激活为主库:来接管服务. 这在其他高可用软件也有这功能, ...
- 面经手册 · 第20篇《Thread 线程,状态转换、方法使用、原理分析》
作者:小傅哥 博客:https://bugstack.cn Github:https://github.com/fuzhengwei/CodeGuide/wiki 沉淀.分享.成长,让自己和他人都能有 ...
- day3(django配置跨域)
1.跨越原理 1. 首先浏览器安全策略限制js ajax跨域访问服务器 2. 如果服务器返回的头部信息中有当前域: // 允许 http://localhost:8080 这个网站打开的页面中的js访 ...
- 第7.27节 Python案例详解: @property装饰器定义属性访问方法getter、setter、deleter
上节详细介绍了利用@property装饰器定义属性的语法,本节通过具体案例来进一步说明. 一. 案例说明 本节的案例是定义Rectangle(长方形)类,为了说明问题,除构造函数外,其他方法都只 ...
- 第8.16节 Python重写自定义类的__str__方法
一. 引言 上节结合案例介绍了重写__repr__方法的关注点,重写__repr__方法的要点是要准确的输出开发人员关注的信息,并便于开发人员使用相关信息.而__str__方法是为最终用户返回类的相关 ...
- PyQt学习随笔:Model/View中设置视图数据项可编辑的方法
在视图对象中调用setEditTriggers方法可以设置视图对象中的数据项是否可编辑以及编辑的触发方法. setEditTriggers方法是QAbstractItemView的方法,语法如下: s ...
- 初识python-名片管理系统v1.0
一.项目说明 本项目分享一个简单的名片管理系统,主要是通过实现简单的功能,来学习python基础. 具体功能有:新建名片.显示全部名片.查询.修改.删除名片 通过对名片的增删改查,来快速看懂pytho ...
- 精品软件-OfficeBox办公神器
办公文档office处理套件,非常齐全,小巧! 官方地址:http://www.wofficebox.com/
- 我的js公共函数合集
export default { isDefin: function(value) { //数据是否被定义 if (value == null || value == &quo ...
- modelViewSet 获取未序列化的数据
1 views/ perform_create 方法的使用 获取未序列化的数据 def perform_create(self, serializer): user_obj=serializer. ...