静态代理和利用反射形成的动态代理(JDK动态代理)
代理模式
代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
静态代理
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动态代理)的更多相关文章
- JDK动态代理深入理解分析并手写简易JDK动态代理(下)
原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-05/27.html 作者:夜月归途 出处:http://www.guitu ...
- JDK动态代理深入理解分析并手写简易JDK动态代理(上)
原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-03/27.html 作者:夜月归途 出处:http://www.guitu ...
- 【原创】分布式之缓存击穿 【原创】自己动手实现静态资源服务器 【原创】自己动手实现JDK动态代理
[原创]分布式之缓存击穿 什么是缓存击穿 在谈论缓存击穿之前,我们先来回忆下从缓存中加载数据的逻辑,如下图所示 因此,如果黑客每次故意查询一个在缓存内必然不存在的数据,导致每次请求都要去存储层去查 ...
- 动态代理学习(一)自己动手模拟JDK动态代理
最近一直在学习Spring的源码,Spring底层大量使用了动态代理.所以花一些时间对动态代理的知识做一下总结. 我们自己动手模拟一个动态代理 对JDK动态代理的源码进行分析 文章目录 场景: 思路: ...
- 代理模式 静态代理、JDK动态代理、Cglib动态代理
1 代理模式 使用代理模式时必须让代理类和被代理类实现相同的接口: 客户端通过代理类对象来调用被代理对象方法时,代理类对象会将所有方法的调用分派到被代理对象上进行反射执行: 在分派的过程中还可以添加前 ...
- java的静态代理、jdk动态代理和cglib动态代理
Java的代理就是客户端不再直接和委托类打交道,而是通过一个中间层来访问,这个中间层就是代理.使用代理有两个好处,一是可以隐藏委托类的实现:二是可以实现客户与委托类之间的解耦,在不修改委托类代码的情况 ...
- 从静态代理,jdk动态代理到cglib动态代理-一文搞懂代理模式
从代理模式到动态代理 代理模式是一种理论上非常简单,但是各种地方的实现往往却非常复杂.本文将从代理模式的基本概念出发,探讨代理模式在java领域的应用与实现.读完本文你将get到以下几点: 为什么需要 ...
- 静态代理与JDK动态代理
demo地址: https://github.com/ZbLeaning/leaning 代理: 为其他对象提供一种代理以控制对这个对象的访问.分为静态代理和动态代理.代理模式的目的就是为真实业务对象 ...
- 代理模式(静态代理、JDK动态代理原理分析、CGLIB动态代理)
代理模式 代理模式是设计模式之一,为一个对象提供一个替身或者占位符以控制对这个对象的访问,它给目标对象提供一个代理对象,由代理对象控制对目标对象的访问. 那么为什么要使用代理模式呢? 1.隔离,客户端 ...
随机推荐
- 著名ERP厂商的SSO单点登录解决方案介绍一
SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.它包括可以将这次主要的登录映射到其他应用中用于同一个用户 ...
- Oracle常用SQL函数整理
--返回ASCII码select ASCII('A') "A的ASCII码" ,ASCII('a') "a的ASSCII码" from dual ; --反向 ...
- Linux命令【第三篇】
执行下面命令时发现提示需要输入密码,请问提示输入的密码是哪个用户的密码. [test@oldboy ~]$ sudo su - oldboy 解答: 输入当前执行命令test账户的密码. 相关说明: ...
- linux之查看系统命令
cpu信息 1.查看逻辑cpu核数 # cat /proc/cpuinfo| grep "processor"| wc -l 2.查看物理cpu个数 # cat /proc/cpu ...
- 学习笔记:发现一个IE版本判断的好方法
web开发就不得不面对浏览器兼容性问题,特别是IE的兼容问题.在前端代码中经常要处理一些兼容格式,为了解决这个问题网上找了找识别浏览器版本的方法. 常规js方法 找到一个方法,还不错,可以识别出各 ...
- .NET面试题系列[4] - C# 基础知识(2)
2 类型转换 面试出现频率:主要考察装箱和拆箱.对于有笔试题的场合也可能会考一些基本的类型转换是否合法. 重要程度:10/10 CLR最重要的特性之一就是类型安全性.在运行时,CLR总是知道一个对象是 ...
- SSH免密码登录
每次用SSH登录服务器都要输入密码,次数多了就觉得有些麻烦,反正是自己个人用的电脑,安全应该有保障,如何能直接登录上去而不需要输入密码呢?其实一句话就讲清楚了:把自己公钥放在服务器上. Linux客户 ...
- Fedora 22中的RPM软件包管理工具
Introduction The RPM Package Manager (RPM) is an open packaging system that runs on Fedora as well a ...
- 2000条你应知的WPF小姿势 基础篇<45-50 Visual Tree&Logic Tree 附带两个小工具>
在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...
- 2000条你应知的WPF小姿势 基础篇<15-21>
在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师,对C#和WPF有着极深的热情.最为出色的是他维护了两个博客:2,000Things You Should Know ...