代理模式

代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

静态代理

1.新建一个接口,这个接口所提供的方法是关于数据库操作的

public interface EmployeeDao {
public void updateSalary();
}

2.建一个目标类实现这个接口,这个目标类是我们要进行的业务

public class EmployeeDaoImpl implements EmployeeDao {
@Override
public void updateSalary() {
System.out.println("您的薪水又有更新");
}
}

3.再建一个代理类,为目标对象提供一种代理,并以控制对这个对象的访问。

public class EmployeeDaoProxy implements EmployeeDao{
private EmployeeDao employeeDao;
private Transaction transaction;
public EmployeeDaoProxy(EmployeeDao employeeDao,Transaction transaction) {
this.employeeDao=employeeDao;
this.transaction=transaction;
} @Override
public void updateSalary() {
this.transaction.startTransaction();
this.employeeDao.updateSalary();
this.transaction.commit();
}

由以上的代码可知:

代理模式的组成包括:目标接口(抽象角色),目标类(真实角色)和代理类(代理角色)。

  • 抽象角色:通过接口声明真实角色实现的业务方法。
  • 代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作
  • 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

4.代理类代理事务的处理,所以需要增加一个事务类


public class Transaction {
public void startTransaction(){
System.out.println("开启事务");
}
public void commit(){
System.out.print("事物提交");
}
}

5.最后我们用一个test case来测试一下


import static org.junit.Assert.*;
import org.junit.Test;
public class ProxyTest {
@Test
public void test() {
EmployeeDao target = new EmployeeDaoImpl();
Transaction transaction = new Transaction();
EmployeeDao proxy = new EmployeeDaoProxy(target,transaction);
proxy.updateSalary();
}
}

假设上面的例子中的接口不只一个方法,或是不只一个接口要用到代理,上面的静态代理的代码就太过繁琐和冗余,所以就出现了jdk的动态代理。

看一下执行情况

开启事务
您的薪水又有更新
事物提交
利用反射动态代理

反射机制指的是程序在运行时能够获取自身的信息。这里的反射一开始不太好理解,其实应该忽略反射的字面意思。只要知道反射其实就是获取Class对象,然后反编译程Java对象,然后访问Java对象的属性、方法等。在Java中,其实所有类的对象都是Class类的实例。每个类被JVM加载之后,就会生成对应对应的Class对象。获得Class对象的方式有以下三种:

1.使用Class类的forName(String className)静态方法,className为类的全名。

Class = Class.forName("Employee");

2.调用某个类的class属性

Class = Employee.class

3.调用某个对象的getClass方法

Employee ee = new Employee();
Class = ee.getClass();

可以从Class中获取的信息包括:构造器、方法、Annotation、内部类、所实现的接口、所继承的父类、对应类的修饰符,所在包类名等基本信息。除此之外,Class对象还可以判断该类是否为接口、枚举、注解类型。再回到上面的代理模式,在JDK中提供Proxy类和InvocationHandler接口生成JDK动态代理类和动态代理对象,Proxy是所有动态代理类的父类,提供创建动态代理类和代理对象的静态方法。

1.创建动态代理类的方法

static Class<?> getProxyClass(ClassLoader loader,Class<?>[]interfaces)

2.创建动态代理实例的方法

static ObjectnewProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler)

同样以上面的例子做示例,1和2中的接口和目标类的编写以及4中的事务处理是相同的,在3中,我们引入拦截器,拦截器是实现动态性的核心

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; /*
* 拦截器
* 引入目标类和事务
* 通过构造器给目标函数和事务赋值
* 填充invoke方法
*
*/
public class EmployeeInterceptor implements InvocationHandler{
private Object target;
private Transaction transaction;
public EmployeeInterceptor(Object target, Transaction transaction) { this.target = target;
this.transaction = transaction;
} /*
* proxy:代表动态代理对象
* method:代表正在执行的方法
* args:代表调用方法是传入的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
this.transaction.startTransaction();
method.invoke(this.target, args);
this.transaction.commit();
return null;
}
}

同样在test case中测试一下:


import static org.junit.Assert.*;
import java.lang.reflect.Proxy;
import org.junit.Test;
public class ProxyTest1 {
@Test
public void test() {
EmployeeDao target = new EmployeeDaoImpl();
Transaction transaction = new Transaction();
EmployeeInterceptor interceptor = new EmployeeInterceptor(target,transaction);
//利用Proxy创建动态代理类
EmployeeDao employeeDao = (EmployeeDao)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), interceptor);
employeeDao.updateSalary();
}
}

最后看一下执行的情况

开启事务
您的薪水又有更新
事物提交

静态代理和利用反射形成的动态代理(JDK动态代理)的更多相关文章

  1. JDK动态代理深入理解分析并手写简易JDK动态代理(下)

    原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-05/27.html 作者:夜月归途 出处:http://www.guitu ...

  2. JDK动态代理深入理解分析并手写简易JDK动态代理(上)

    原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-03/27.html 作者:夜月归途 出处:http://www.guitu ...

  3. 【原创】分布式之缓存击穿 【原创】自己动手实现静态资源服务器 【原创】自己动手实现JDK动态代理

    [原创]分布式之缓存击穿   什么是缓存击穿 在谈论缓存击穿之前,我们先来回忆下从缓存中加载数据的逻辑,如下图所示 因此,如果黑客每次故意查询一个在缓存内必然不存在的数据,导致每次请求都要去存储层去查 ...

  4. 动态代理学习(一)自己动手模拟JDK动态代理

    最近一直在学习Spring的源码,Spring底层大量使用了动态代理.所以花一些时间对动态代理的知识做一下总结. 我们自己动手模拟一个动态代理 对JDK动态代理的源码进行分析 文章目录 场景: 思路: ...

  5. 代理模式 静态代理、JDK动态代理、Cglib动态代理

    1 代理模式 使用代理模式时必须让代理类和被代理类实现相同的接口: 客户端通过代理类对象来调用被代理对象方法时,代理类对象会将所有方法的调用分派到被代理对象上进行反射执行: 在分派的过程中还可以添加前 ...

  6. java的静态代理、jdk动态代理和cglib动态代理

    Java的代理就是客户端不再直接和委托类打交道,而是通过一个中间层来访问,这个中间层就是代理.使用代理有两个好处,一是可以隐藏委托类的实现:二是可以实现客户与委托类之间的解耦,在不修改委托类代码的情况 ...

  7. 从静态代理,jdk动态代理到cglib动态代理-一文搞懂代理模式

    从代理模式到动态代理 代理模式是一种理论上非常简单,但是各种地方的实现往往却非常复杂.本文将从代理模式的基本概念出发,探讨代理模式在java领域的应用与实现.读完本文你将get到以下几点: 为什么需要 ...

  8. 静态代理与JDK动态代理

    demo地址: https://github.com/ZbLeaning/leaning 代理: 为其他对象提供一种代理以控制对这个对象的访问.分为静态代理和动态代理.代理模式的目的就是为真实业务对象 ...

  9. 代理模式(静态代理、JDK动态代理原理分析、CGLIB动态代理)

    代理模式 代理模式是设计模式之一,为一个对象提供一个替身或者占位符以控制对这个对象的访问,它给目标对象提供一个代理对象,由代理对象控制对目标对象的访问. 那么为什么要使用代理模式呢? 1.隔离,客户端 ...

随机推荐

  1. GIT笔记命令行(1)

    Git简单易用,只要输入git就可以列出他的所有参数 C:\Users\spu>git usage: git [--version] [--help] [-C <path>] [-c ...

  2. i++、++i 、i--、--i

    总结: i++ 先用后加, ++i先加后用: i--先用后减, --i先减后用: //int i = 1; //Console.WriteLine(i);//1 //Console.WriteLine ...

  3. ReSharper详解Index0

    JetBrains ReSharper可以帮助Visual Studio用户编写出更好的代码.支持对C#,VB.NET,XAML,JavaScript,TypeScript,JSON,XML,HTML ...

  4. windows10简单试用(多图,连薛定谔的猫都杀死了)

    为了大家看起来方便,我的截图都是gif的,比较小,但是颜色会有色差,相信大家不介意的 昨天windows10可以下载第一时间就下了玩玩 由于是技术预览,所以不打算替换之前的系统,只装在虚拟机里玩玩就好 ...

  5. C++ std::forward_list

    std::forward_list template < class T, class Alloc = allocator > class forward_list; Forward li ...

  6. C#中,双屏/两屏/三屏/多屏跳转判断

    之前伤脑筋写过一次在Web中,JS,ActiveXObject去读取显示器数量.分辨率去判断单双屏跳转. 那么在客户端中,用C#去读取硬件信息,更方便更容易! 思路参考代码: ) { //此显示器是否 ...

  7. JS对象继承篇

    JS对象继承篇 ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的 原型链 其基本思路是利用原型让一个引用类型继承另一个引用类型的属性和方法 function Person() ...

  8. JS创建对象篇

    JS创建对象篇 Object构造函数创建 var person = new Object(); person.name = "Tom"; person.age = 10; pers ...

  9. [CentOs7]搭建ftp服务器(2)——添加用户

    摘要 上篇文章完成了ftp服务器的安装与匿名访问的内容,当然出于安全的考虑是不允许匿名访问服务器的,所以就有了本篇的内容 ,为ftp服务器添加用户,用改用户进行访问. vsftpd添加用户 FTP用户 ...

  10. 关于for循环中,定义的i的作用域的问题。

    for(var i=0;i<2;i++){ console.log(i) } console.log(i) 经过测试:在IE9+,谷歌,火狐中.都出现了0,1,2三个值. 所以其作用域在整个上下 ...