一、静态代理
Subject.java
package com.test.staticproxy;
/**
* 需要代理的接口方法
*/
public interface Subject {
// 需要代理的方法
void request();
}
RealSubject.java
package com.test.staticproxy;
/**
* 真实对象
*/
public class RealSubject implements Subject{
@Override
public void request() {
System.out.println("真正的角色");
}
}
Proxy.java
package com.test.staticproxy;
/**
* 代理者
* 代码模式重点:需要持有一个真实对象
* 被代理的对象就称为真实对象
*
*/
public class Proxy implements Subject{
//真实对象
private Subject subject;
public Proxy(Subject subject) {
this.subject = subject;
}
@Override
public void request() {
System.out.println("begin");
subject.request();
System.out.println("end");
}
}
代码测试入口函数
Test.java
package com.test.staticproxy;
import javax.security.auth.Subject;
public class Test {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
Proxy proxy = new Proxy(realSubject);
proxy.request();
}
}
输出结果:
begin
真正的角色
end
二、动态代理
动态代理中,代理类并不是在Java代码中实现,而是在运行时期生成,相比静态代理,动态代理可用很方便的对委托类的方法进行统一处理。
Subject.java
package com.test.staticproxy;
/**
* 需要代理的接口方法
*/
public interface Subject {
// 需要代理的方法
void request();
}
RealSubject.java
package com.test.staticproxy;
/**
* 真实对象
*/
public class RealSubject implements Subject{
@Override
public void request() {
System.out.println("真正的角色");
}
}
动态代理的核心类,只要实现动态代理必须要实现InvocationHandler 接口。
静态代理只能在外层进行包装,动态代理能够代理任何方法,作用发生在运行时。
MyInvocationHandler.java
package com.test.dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
// 真实对象类型
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
/**
* 调用invoke
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
/**
* method:当前代理的方法
* target:代理的真实对象
* args: 参数(形参)类型
*/
Object result = method.invoke(target, args);
System.out.println("after");
return result;
}
}
如果有多个方法的话,可以在invoke()方法中进行相关的接口方法判断
比如:
Object result = null;
if ("request".equals(method.getName())) {
result = method.invoke(target, args);
}
测试代码主入口
Test.java
package com.test.dynamicproxy;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
Subject subject = new RealSubject();
//实例化
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(subject);
/**
* 第一个参数(classLoader): contextLoader
* 第二个参数(接口数组):决定返回代理的对象实现了哪些接口
* 第三个参数:代理时,需要处理具体的操作
*/
Subject proxy = (Subject) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
subject.getClass().getInterfaces(),
myInvocationHandler);
proxy.request();
}
}
上面获取接口数组的方法也可以采用这种方式:
new Class[]{Subject.class}
但是个人推荐还是这种方法更好些
subject.getClass().getInterfaces()
proxy.request();
public Object invoke(Object proxy, Method method, Object[] args)
执行proxy.request();这个语句时,首先会来到MyInvocationHandler类中,调用invoke()方法,将proxy.request()语句中的proxy对象传给invoke()方法中的第一个参数proxy,将当前调用的方法request传给invoke()方法中的第二个参数method,其实也就是Subject中的request()方法,再将Subject类中request()方法中的参数传给invoke()方法中的第三个参数args,这个里面参数为空。
输出结果:
before
真正的角色
after
三、角色
-
Subject
抽象主题角色,是一个接口,该接口是对象和它的代理公用的接口。 -
RealSubject
真实主题角色,是实现抽象主题接口的类 -
Proxy
代理角色,内部含有对真实对象RealSubject的引用,从而可以操作真实对象。代理对象提供与真实对象相同的接口,以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
实现动态代理关键技术是反射。