即Proxy Pattern,23种java常用设计模式之一。代理模式的定义:对其他对象提供一种代理以控制对这个对象的访问。
//接口类Italk
public interface Italk {
public void talk(String msg);
}
//实现类people
public class People implements Italk {
public String username;
public String age;
public String getName() {
return username;
}
public void setName(String name) {
this.username= name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public People(String name1, String age1) {
this.username= name1;
this.age = age1;
}
public void talk(String msg) {
System.out.println(msg+"!你好,我是"+username+",我年龄是"+age);
}
}
//代理类talkProxy
public class TalkProxy implements Italk {
Italk talker;
public TalkProxy (Italk talker) {
//super();
this.talker=talker;
}
public void talk(String msg) {
talker.talk(msg);
}
public void talk(String msg,String singname) {
talker.talk(msg);
sing(singname);
}
private void sing(String singname){
System.out.println("唱歌:"+singname);
}
}
//应用端myProxyTest
public class MyProxyTest {
/**代理模式
* @param args
*/
public static void main(String[] args) {
//不需要执行额外方法的
Italk people1=new People("湖海散人","18");
people1.talk("No ProXY Test");
System.out.println("-----------------------------");
//需要执行额外方法的
TalkProxy talker=new TalkProxy(people1);
talker.talk("ProXY Test","七里香");
}
}
static class DelegatedScheduledExecutorService
extends DelegatedExecutorService
implements ScheduledExecutorService {
private final ScheduledExecutorService e;
DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
super(executor);
e = executor;
}
public ScheduledFuture> schedule(Runnable command, long delay, TimeUnit unit) {
return e.schedule(command, delay, unit);
}
public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) {
return e.schedule(callable, delay, unit);
}
public ScheduledFuture> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
return e.scheduleAtFixedRate(command, initialDelay, period, unit);
}
public ScheduledFuture> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
return e.scheduleWithFixedDelay(command, initialDelay, delay, unit);
}
}
上面代码主要屏蔽的是ScheduledExecutorService实现类的方法,因为我newSingleThreadScheduledExecutor的功能远远没有newScheduledThreadPool(5)功能多,但是他们都是ScheduledExecutorService的子类,所以只能屏蔽
newSingleThreadScheduledExecutor不需要的方法(上面主要是在API设计上考虑屏蔽的,并不是严格意义上的屏蔽,不让用户使用那种)。
下面主要讲解一下动态代理:
假如有这样一种场景,我们项目使用第三方类库,但是非开源的,我们无法修改源码(不考虑破解反编译之类的),只能在现有方法上做增强,但是如果使用代理模式为每一个类写一个代理类的话,当需要被代理的类特别多的时候是工作量是不无法忍受的。那么我们就可以使用动态代理实现,此处使用JDK动态代理:
非开源类库代码如下:
public interface Helloworld {
public void sayHello();
public void sayBye();
}
public class HelloworldImpl implements Helloworld{
public void sayHello() {
System.out.println("HelloworldImpl sayHello ...");
}
public void sayBye() {
System.out.println("HelloworldImpl sayBye ...");
}
}
以上为非开源代码。
接下来我们需要序sayHello和sayBye前后打印日志操作的话,我们只能使用JDK的动态代理模式实现,代理类需要实现java.lang.reflect.InvocationHandler接口:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class HelloWorldInvocationHandler implements InvocationHandler {
private Helloworld agent;
public HelloWorldInvocationHandler (Helloworld agent) {
super();
this.agent = agent;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前面日志记录完毕");
Object result = method.invoke(agent, args);
System.out.println("后面日志记录完毕");
return result;
}
public void sayLove() {
System.out.println("I love you !");
}
}
public class MainProxy {
public static void main(String[] args) throws Exception {
//测试代码还有另一种写法
// 生成HelloWorld的代理类:class com.sun.proxy.$Proxy0
Class> proxyClass = Proxy.getProxyClass(MainProxy.class.getClassLoader(), Helloworld.class);
final Constructor> cons = proxyClass.getConstructor(InvocationHandler.class);
// com.daxin.proxy.jdk.MyInvocationHandler
final InvocationHandler ih = new HelloWorldInvocationHandler(new HelloworldImpl());
// System.out.println(ih);
// HelloworldImpl
Helloworld helloWorld = (Helloworld) cons.newInstance(ih);
helloWorld.sayHello();
helloWorld.sayBye();
}
}
前面日志记录完毕
HelloworldImpl sayHello ...
后面日志记录完毕
前面日志记录完毕
HelloworldImpl sayBye ...
后面日志记录完毕
进行代码解释:
Class> proxyClass = Proxy.getProxyClass(MainProxy.class.getClassLoader(), Helloworld.class);
字节码如下:
package com.sun.proxy;
import com.daxin.proxy.jdk.Helloworld;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
//注意:this.h成员其实就是Proxy类中的成员,类型为:InvocationHandler,也就是我们自己定义InvocationHandler
public final class $Proxy0 extends Proxy
implements Helloworld
{
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler paramInvocationHandler)
throws
{
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject)
throws
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void sayHello()
throws
{
try
{
this.h.invoke(this, m3, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
throws
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m3 = Class.forName("com.daxin.proxy.jdk.Helloworld").getMethod("sayHello", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}
final Constructor> cons = proxyClass.getConstructor(InvocationHandler.class);
作用是为了获取proxyClass的构造参数为InvocationHandler类型的构造器。
final InvocationHandler ih = new HelloWorldInvocationHandler(new HelloworldImpl());
Helloworld helloWorld = (Helloworld) cons.newInstance(ih);
真正产生代理对象的核心代码。
注意:当你对代理对象调用System.out.println(helloWorld);时候,你会发现输出的是:com.daxin.proxy.jdk.HelloworldImpl@7d4991ad ,此时是不是很好奇,为什么不是Proxy代理对象呢 ? 现在你可以回头看一下生成的字节码的toString了。
public final String toString()
throws
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
注意:这里面的this.h,h是继承至Proxy类的成,就是我们自己定义的InvocationHandler。然后调用m2(m2就是toString方法)。此时
InvocationHandler里面的invoke代码就是如下了:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前面日志记录完毕");
//method为toString ,所以是在对agent调用toString方法,而agent方法是HelloworldImpl
Object result = method.invoke(agent, args);
System.out.println("后面日志记录完毕");
return result;
}
Helloworld helloWorld = (Helloworld) cons.newInstance(ih);
System.out.println(helloWorld);
输出为com.daxin.proxy.jdk.HelloworldImpl@7d4991ad
上面的实现是基于JDK实现的动态代理,还有cglib的实现,以后进行补充