定义
- 代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即通过代理
对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的
功能操作,即扩展目标对象的功能。 - 被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象
- 代理模式有不同的形式, 主要有三种 **静态代理、动态代理 **(JDK代理、接口代
理)和 Cglib代理 (可以在内存动态的创建对象,而不需要实现接口, 他是属于
动态代理的范畴)
静态代理
- 优点:在不修改目标对象的功能前提下,能通过代理对象对目标功能扩展
- 缺点:因为代理对象需要与目标对象实现一样的忌口,所有会有很多代理类;一旦接口增加方法,目标对象与代理对象都要维护
public class test9 {
public static void main(String[] args) {
ProxyRoommate p = new ProxyRoommate(new RealSubjectI());
p.buyKole();
//打了一顿篮球
//去买可乐
//被篮球打了一顿
}
}
//共同行为接口
interface ISubject {
void buyKole();
}
class RealSubjectI implements ISubject {
@Override
public void buyKole() {
System.out.println("去买可乐");
}
}
class ProxyRoommate implements ISubject {
//维护一个目标对象
private RealSubjectI realSubject;
//构造器,传入一个被代理的对象
public ProxyRoommate(RealSubjectI realSubject) {
this.realSubject = realSubject;
}
@Override
public void buyKole() {
System.out.println("打了一顿篮球");
//这个方法前后都可以做很多事
realSubject.buyKole();
System.out.println("被篮球打了一顿");
}
}
JDK代理
- 代理类所在包:java.lang.reflect.Proxy
- JDK实现代理只需要使用newProxyInstance方法,但是该方法需要接收三个参数,完整的写法是:
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
- 注意该方法是在Proxy类中是静态方法,且接收的三个参数依次为:
ClassLoader loader,:指定当前目标对象使用类加载器,获取加载器的方法是固定的
Class<?>[] interfaces,:目标对象实现的接口的类型,使用泛型方式确认类型
InvocationHandler h:事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class test9 {
public static void main(String[] args) {
ISubject p = new RealSubjectI();
ISubject proxyInstance =(ISubject) new ProxyRoommate(p).getProxyInstance();
proxyInstance.buyKole();
System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++");
proxyInstance.buyKole("小黄");
/**
JDK代理开始
去买可乐
JDK代理结束
JDK代理开始
小黄让我去买可乐
J DK代理结束
*/
}
}
//共同行为接口
interface ISubject {
void buyKole();
void buyKole(String name);
}
class RealSubjectI implements ISubject {
@Override
public void buyKole() {
System.out.println("去买可乐");
}
@Override
public void buyKole(String name) {
System.out.println(name+"让我去买可乐");
}
}
class ProxyRoommate {
//维护一个目标对象
private Object object;
//构造器,传入一个被代理的对象
public ProxyRoommate(Object object) {
this.object = object;
}
//说明
/*
* public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
//1. ClassLoader loader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定
//2. Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型方法确认类型
//3. InvocationHandler h : 事情处理,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入
*/
//给目标对象 生成一个代理对象
public Object getProxyInstance() {
return Proxy.newProxyInstance(object.getClass().getClassLoader(),
object.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK代理开始");
Object invoke = method.invoke(object, args);
System.out.println("JDK代理结束");
return invoke;
}
}
);
}
}
CGlib代理
- 静态代理和JDK代理模式都要求目标对象是实现一个接口,但是有时候目标对象只
- 是一个单独的对象,并没有实现任何的接口,这个时候可使用目标对象子类来实现 代理-这就是Cglib代理
- 目标对象需要实现接口,用JDK代理
- 目标对象不需要实现接口,用Cglib代理
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class test9 {
public static void main(String[] args) {
RealSubjectI o = new RealSubjectI();
RealSubjectI proxyInstance =(RealSubjectI) new ProxyRoommate(o).getProxyInstance();
proxyInstance.buyKole();
System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++");
proxyInstance.buyKole("小黄");
/**
Cglib代理模式 ~~ 开始
去买可乐
Cglib代理模式 ~~ 提交
+++++++++++++++++++++++++++++++++++++++++++++++++
Cglib代理模式 ~~ 开始
小黄让我去买可乐
Cglib代理模式 ~~ 提交
*/
}
}
class RealSubjectI {
public void buyKole() {
System.out.println("去买可乐");
}
public void buyKole(String name) {
System.out.println(name + "让我去买可乐");
}
}
class ProxyRoommate implements MethodInterceptor {
//维护一个目标对象
private Object object;
//构造器,传入一个被代理的对象
public ProxyRoommate(Object object) {
this.object = object;
}
//返回一个代理对象: 是 target 对象的代理对象
public Object getProxyInstance() {
//1. 创建一个工具类
Enhancer enhancer = new Enhancer();
//2. 设置父类
enhancer.setSuperclass(object.getClass());
//3. 设置回调函数
enhancer.setCallback(this);
//4. 创建子类对象,即代理对象
return enhancer.create();
}
//重写 intercept 方法,会调用目标对象的方法
@Override
public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
// TODO Auto-generated method stub
System.out.println("Cglib代理模式 ~~ 开始");
Object returnVal = method.invoke(object, args);
System.out.println("Cglib代理模式 ~~ 提交");
return returnVal;
}
}