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、代理模式
代理模式分为一下几种
-
静态代理模式
- 动态代理模式
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差不多了
静态代理优点以及缺点
- 优点:
可扩展性强
代码简洁不影响源代码的使用
2.缺点
每一次代理都需要产生一个代理类
重复的代理类使得代码效率过低
4、动态代理模式
1、JDK动态代理
2、CGLIB动态代理
5、这两种动态代理模式有什么区别呢?
- 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