代理模式的简易讲解

版权声明:@412958751 https://blog.csdn.net/Jake_JJJ/article/details/81515383

1、什么是代理模式?

@百度:

即Proxy Pattern,23种常用的面向对象软件的设计模式之一。(设计模式的说法源自《设计模式》一书,原名《Design Patterns: Elements of Reusable Object-Oriented Software》。1995年出版,出版社:Addison Wesly Longman.Inc。该书提出了23种基本设计模式,第一次将设计模式提升到理论高度,并将之规范化。)

 

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

@个人:

代理模式是属于常见的23中设计模式之一。

代理模式的定义:代理模式是在某些对象不能创建或者不能复合条件的引用一个对象,从而产生的代理对象(也就是代理模式)。

例如:

我编写一个接口,但是我没编写它的实现类,那么我怎么去成功的实现以及使用这个方法呢?

如下列代码:

package com.nyhs.dao;

public interface Demo {

	void add();
	
}

这是demo中的一个add也就是一个添加方法。

但是我没有这个类的实现类,那么我该怎么实现这个方法并且成功运行我想要运行的代码呢?

这时候代理模式就产生了。

2、代理模式

代理模式分为一下几种

  1. 静态代理模式

  2. 动态代理模式

3、静态代理模式

例:

package com.nyhs.demo.proxy;

import com.nyhs.demo.demo;

public class Proxy implements demo {

	public void add() {
		System.out.println("代理对象中");
	}

}

如上面代理所示这便是静态代理对象,(个人感觉这和实现类没什么区别),但的的确确的代理是通过这种形式的方式去实现的,请看这段代码

package com.nyhs.demo.proxy;

import com.nyhs.demo.demo;

public class Proxy implements demo {

	// 实际代理对象
	private Object proxyObject;

	public Proxy(Object proxyObject) {
		this.proxyObject = proxyObject;
	}

	public void add() {
		System.out.println("代理对象中");
	}

}

这是否就像是SpringAop中呢?(这时候可能还不会感觉这代码哪里就像是代理模式,那我改造一下)

package com.nyhs.demo.proxy;

import java.lang.reflect.Method;

import com.nyhs.demo.demo;

public class Proxy implements demo {

	// 实际代理对象子类
	private Object proxyObject;

	public Proxy(Object proxyObject) {
		this.proxyObject = proxyObject;
	}

	public void add() {
		System.out.println("代理对象中");
		// 通过反射获取对象
		Class classz = proxyObject.getClass();
		try {
			// 通过反射获取add方法
			Method method = classz.getDeclaredMethod("add");
			// 执行代码前
			System.out.println("执行前,前置通知");
			// 执行传入对象的add方法
			method.invoke(proxyObject, method);
			// 执行代码后
			System.out.println("执行后,后置通知");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

此时该代理类就与AOP差不多了

静态代理优点以及缺点

  1. 优点:

可扩展性强

代码简洁不影响源代码的使用

     2.缺点

每一次代理都需要产生一个代理类

重复的代理类使得代码效率过低

4、动态代理模式

1、JDK动态代理

2、CGLIB动态代理

5、这两种动态代理模式有什么区别呢?

  1. JDK动态代理是基于反射来实现的,也就是上面的例子

例:

package com.nyhs.test;

import java.lang.reflect.Proxy;

import com.nyhs.demo.Demo;
import com.nyhs.demo.proxy.ProxyDemo;

public class Test {
	public static void main(String[] args) {
		// 对应参数为:1、类加载器,为了实时能够获取动态代理内容2、需要代理的类接口,实际代理方法
		Demo demo = (Demo) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[] { Demo.class },
				new ProxyDemo(Demo.class));
	}
}
package com.nyhs.demo.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ProxyDemo implements InvocationHandler {

	// 代理对象
	private Object object;

	public ProxyDemo(Object object) {
		this.object = object;
	}
    //参数为:1、实际代理对象2、代理对象方法3、调用所代理的方法传入的参数
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		return null;
	}

}

这里实际代理类是需要继承InvocationHandler类,并且实现invoke方法。

这便实现了动态代理,是基于反射来实现代理。

但是其底层不仅仅是使用反射方式进行实现代理操作,也通过的字节码方式去进行代理

动态代理其优点在于不重复的去创建代理类。

2、CGLIB动态代理

CGLIB动态代理是通过字节码技术来实现的,底层是通过使用ASM字节码框架,在JAVA 中,JVM中实现虚拟代理类,通过拦截所代理类调用的方法,经行横向切入(AOP)来进行实现的

@两种动态代理的区别在于

1、JDK是需要一个接口来进行代理的,这样才能进行代理,个人感觉(原因是在于类于类之间存在关联才能进行多态创建)

2、CGLIB动态代理,则不需要接口就能进行代理,因为底层使用的是字节码技术,但是底层实现是通过直接继承的方式实现其子类,再进行增强、重构代码,然后进行字节码修改,需要注意因为是继承方式,所以不能代理final类(final类是不能被继承的)。

在这里需要提醒一下,CGLIB的性能,效率会比JDK的动态代理快上一点

但是经过专人测试,结果在使用JDK1.7或1.8与CGLIB,在相同环境下进行1w次测试,JDK效率比CGLIB快上20%,2333

猜你喜欢

转载自blog.csdn.net/Jake_JJJ/article/details/81515383