Java静态代理

Jdk动态代理

java代理模式

即Proxy Pattern,23种java常用设计模式之一。代理模式的定义:对其他对象提供一种代理以控制对这个对象的访问。

原理:

代理模式的主要作用是为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式的思想是为了提供额外的处理或者不同的操作而在实际对象与调用者之间插入一个代理对象。这些额外的操作通常需要与实际对象进行通信。
应用场景:
假设有一组对象都实现同一个接口,实现同样的方法,但这组对象中有一部分对象需要有单独的方法,传统的笨办法是在每一个应用端都加上这个单独的方法,但是代码重用性低,耦合性高。
public interface IPerson {
//定义代理接口类
public abstract void sleep(); public abstract void eating(); }

实现类:

//实现类
public class Person implements IPerson{ public void sleep(){ System.out.println("睡觉中!"); } public void eating(){ System.out.println("正在吃饭中!"); }

静态代理类:

public class PersonProxy implements IPerson {

    private IPerson person;

    private Logger logger = Logger.getLogger(String.valueOf(PersonProxy.class));

    public PersonProxy(Person person) {
this.person = person;
} @Override
public void sleep() { logger.info("开始执行时间: "+ new Date()); person.eating(); logger.info("执行结束时间: "+ new Date()); } @Override
public void eating() {
logger.info("开始执行时间:"+ new Date()); person.sleep(); logger.info("执行结束时间: "+ new Date()); } }

测试类:

 /**
* 静态代理
*/
@Test
public void persontest(){
IPerson proxy = new PersonProxy(new Person());
proxy.eating();
proxy.sleep();
}

静态代理的弊端:

一个代理接口只能服务于一种类型的对象.对于稍大点的项目根本无法胜任.

3  解决方案2-动态代理

在JDK1.3之后加入了可协助开发的动态代理功能.不必为特定对象与方法编写特定的代理对象,使用动态代理,可以使得一个处理者(Handler)服务于各个对象.

一个处理者的类设计必须实现java.lang.reflect.InvocationHandler接口.

通过InvocationHandler接口实现的动态代理只能代理接口的实现类.

动态代理概念及类图

动态代理跟静态代理一个最大的区别就是:动态代理是在运行时刻动态的创建出代理类及其对象。上篇中的静态代理是在编译的时候就确定了代理类具体类型,如果有多个类需要代理,那么就得创建多个。还有一点,如果Subject中新增了一个方法,那么对应的实现接口的类中也要相应的实现这些方法。

动态代理的做法:在运行时刻,可以动态创建出一个实现了多个接口的代理类。每个代理类的对象都会关联一个表示内部处理逻辑的InvocationHandler接 口的实现。当使用者调用了代理对象所代理的接口中的方法的时候,这个调用的信息会被传递给InvocationHandler的invoke方法。在 invoke方法的参数中可以获取到代理对象、方法对应的Method对象和调用的实际参数。invoke方法的返回值被返回给使用者。这种做法实际上相 当于对方法调用进行了拦截。
类图如下所示:
 
 
 
 

动态代理实现:

处理者代理类:

public class DynaProxyHandler implements InvocationHandler {

    private Logger logger = Logger.getLogger(String.valueOf(DynaProxyHandler.class));

    private Object target;//被代理对象
public void setTarget(Object target) {
this.target = target;
} public DynaProxyHandler(IPerson persons) {
this.target=persons;
}
public DynaProxyHandler() {
}
@Override
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable { logger.info("执行开始时间:" + new Date());
// System.out.println(method);
Object result = method.invoke(target, args); logger.info("执行结束时间:" + new Date()); return result;//返回method执行结果 } }

生产代理对象的工厂:

/**
* 动态代理工厂
*/
public class DynaProxyFactory {
//obj为被代理对象 public static Object getProxy(Object obj){ DynaProxyHandler handler = new DynaProxyHandler();
CjlibProxy cjlibProxy=new CjlibProxy(); handler.setTarget(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler); } }

动态代理测试:

 //测试动态代理
@Test
public void DynaProxyHandler(){
IPerson person = (IPerson) DynaProxyFactory.getProxy(new Person());
//返回代理类,代理类是JVM在内存中动态创建的,该类实现传入的接口数组的全部接口(的全部方法).
person.eating();
person.sleep();
}

将静动态结合测试:

  @Test
public void agentAndDynaProxyHandler(){
//是我们要代理的真实对象
IPerson persons = (IPerson) new Person();
//我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
InvocationHandler handler = new DynaProxyHandler(persons);
/*
* 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数
* 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象
* 第二个参数person1.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了
* 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
*/
IPerson person = (IPerson) Proxy.newProxyInstance(handler.getClass().getClassLoader(), persons.getClass().getInterfaces(), handler);
person.eating();
person.sleep();
}

Cjlib动态代理:

代理类:

public class CjlibProxy implements MethodInterceptor{

    private Enhancer enhancer=new Enhancer();
//创建一个方法来完成创建代理对象
public Object createInstance(Class c){
//设置公共类接口
enhancer.setSuperclass(c);
enhancer.setCallback(this);
return enhancer.create(); //创建代理类对象.
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("====================");
methodProxy.invokeSuper(o,objects);
System.out.println("=================结束");
return null;
}
}

测试类:

 /**
* Cjlib动态代理
*/
@Test
public void cjlibTest(){
IPerson iPerson= (IPerson) new Person();
InvocationHandler invocationHandler=new DynaProxyHandler(iPerson);
IPerson person = (IPerson) Proxy.newProxyInstance(iPerson.getClass().getClassLoader(), iPerson.getClass().getInterfaces(), invocationHandler);
person.eating();
person.sleep(); }

spring的静态代理和动态代理的更多相关文章

  1. java中代理,静态代理,动态代理以及spring aop代理方式,实现原理统一汇总

    若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. ...

  2. java:struts框架2(方法的动态和静态调用,获取Servlet API三种方式(推荐IOC(控制反转)),拦截器,静态代理和动态代理(Spring AOP))

    1.方法的静态和动态调用: struts.xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCT ...

  3. Spring专题1: 静态代理和动态代理

    合集目录 Spring专题1: 静态代理和动态代理 为什么需要代理模式? 代理对象处于访问者和被访问者之间,可以隔离这两者之间的直接交互,访问者与代理对象打交道就好像在跟被访者者打交道一样,因为代理者 ...

  4. spring——AOP(静态代理、动态代理、AOP)

    一.代理模式 代理模式的分类: 静态代理 动态代理 从租房子开始讲起:中介与房东有同一的目标在于租房 1.静态代理 静态代理角色分析: 抽象角色:一般使用接口或者抽象类来实现(这里为租房接口) pub ...

  5. spring静态代理和动态代理

    本节要点: Java静态代理 Jdk动态代理 1 面向对象设计思想遇到的问题 在传统OOP编程里以对象为核心,并通过对象之间的协作来形成一个完整的软件功能,由于对象可以继承,因此我们可以把具有相同功能 ...

  6. Spring 静态代理和动态代理

    现在我们来模拟一下,某位学生去考试. 假设他(小明)正常的考试. 运行结果:        结果: 突然某一天,他睡过头了,来不急去考试,所有他打算叫另一个人(Cheater)去代替他考试. 运行结果 ...

  7. Spring AOP里的静态代理和动态代理,你真的了解嘛?

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

  8. Atitit 代理CGLIB 动态代理 AspectJ静态代理区别

    Atitit 代理CGLIB 动态代理 AspectJ静态代理区别 1.1. AOP 代理主要分为静态代理和动态代理两大类,静态代理以 AspectJ 为代表:而动态代理则以 spring AOP 为 ...

  9. 【Java】代处理?代理模式 - 静态代理,动态代理

    >不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算, ...

随机推荐

  1. 兼容ie的半透明背景颜色过滤器,会影响事件的触发.

    兼容ie的半透明背景颜色过滤器,会影响事件的触发.

  2. 【Android】自己定义相机的实现(支持连续拍照、前后摄像头切换、连续对焦)

    ~转载请注明http://blog.csdn.net/u013015161/article/details/46921257 介绍 这几天.写了一个自己定义照相机的demo.支持连续拍照和摄像头切换. ...

  3. 超简单Centos+Docker+Halo搭建java向博客

    首先,我就当你们了解docker基本知识了. 直接开始,全新的系统. 1. 安装Docker 移除旧的版本:  $ sudo yum remove docker \                  ...

  4. go-007-条件语句

    一.概述 条件语句需要开发者通过指定一个或多个条件,并通过测试条件是否为 true 来决定是否执行指定语句,并在条件为 false 的情况在执行另外的语句. 1.if结构 if 布尔表达式 { /* ...

  5. IDOC 实例测试

    这份文档主要是自己学习IDOC的一些练习过程及心得,可能讲的不全面,但应该可以帮助大家了解IDOC的一些工作方式. IDOC或者说是ALE,事实上,是SAP用于分布和集成数据的一种方式.所以,我个人就 ...

  6. Using Bluetooth LE with Go (Golang)

    Using Bluetooth LE with Go (Golang)  Gatt is a Go package, which provides developers to create BLE a ...

  7. python 学习笔记(循环,print的几种写法,操作符)

    一.循环( for, while) while循环是指在给定的条件成立时(true),执行循环体,否则退出循环.for循环是指重复执行语句. break 在需要时终止for /while循环 cont ...

  8. Creating an generated Earth AVI with C++

    Creating an generated Earth AVI with C++        EarthGenerator.cpp /*    EarthGenerator.cpp An examp ...

  9. vue 项目中assets文件夹与static文件夹引用的区别

    首先,assets文件夹和static文件夹在vue-cli生成的项目中,都是用来存放静态资源的. 1.assets目录中的文件会被webpack处理解析为模块依赖,只支持相对路径形式.build的时 ...

  10. property函数的使用

    描述 property函数的作用是在新式类中返回属性值 在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改 s=Student() s.score= ...