JDK动态代理与静态代理(一)

顾名思义为某个类的对象提供代理服务,协助该对象解决核心方法以外的问题。

静态代理:委托类对象运行之前,代理类对象已经存在。且服务于某些特定类对象(同一个接口下)。

静态代理举例:

public interface Service {
	void add();
	void del();
	void update();
	void query();
}

/**
 * 用户实际操作
 */
public class UserServiceImpl implements Service {

	public void add() {
		System.out.println("用户添加操作!");
	}

	public void del() {
		System.out.println("用户删除操作!");
	}

	public void update() {
		System.out.println("用户更新操作!");
	}

	public void query() {
		System.out.println("用户查询操作!");
	}

}

/**
 * 记录用户操作的代理类:
 */
public class UserLogProxy implements Service {
	private Service  userService;
	public UserLogProxy(Service  userService){
		this.userService=userService;
	}
	public void add() {
		before("add");
		userService.add();
		after("add");
	}

	public void del() {
		before("del");
		userService.del();
		after("del");
	}

	public void update() {
		before("update");
		userService.update();
		after("update");
	}

	public void query() {

	}
	public void before(String method){
		System.out.println("用户开始执行"+method+"方法!");
	}
	public void after(String method){
		System.out.println("用户执行完"+method+"方法!");
	}
}

	/**
	 * 测试方法执行
	 */
	public static void main(String[] args) {
			Service user=new UserLogProxy(new UserServiceImpl() );
			user.add();
			user.del();
	}

优点:代码类不需要了解委托类的具体实现,客户端方法调用时,只需要知道代理类对象即可。

缺点:代码冗余,维护性差。代理类和委托类实现了相同接口,如果我接口中有上百个方法,则代理类需要手动对上百个方法的添加日志记录信息。





动态代理:

程序运行时通过反射动态产生代理类。

/**
 *日志处理器
 */
public class LogProxyHandler implements InvocationHandler  {
	public Object targetObject;//目标对象
	public Object newProxyInstance(Object targetObject){
		this.targetObject=targetObject;
		/**
		 * 生成代理类实例:
		 * 第一个参数:指定代理类的类加载器。需要将其指定为和目标对象同一个类加载器 
		 * 第二个参数:代理类要实现的接口。使用目标对象的接口
		 * 第三个参数:执行方法时,需要执行哪个InvocationHandler的invoke方法  
		 */
		return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
				targetObject.getClass().getInterfaces(), this);
	}
	/**
	 * 代理类执行的方法
	 */
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		before(method.getName());
		method.invoke(targetObject, args);
		after(method.getName());
		return null;
	}

	//扩展模块
	private void before(String name){
		System.out.println(name+"方法执行开始!");
	}
	//扩展模块
	private void after(String name){
		System.out.println(name+"方法执行结束!");
	}
}

public class Test {
	/**
	 * 测试方法执行
	 */
	public static void main(String[] args) {
		
		Service service = (Service)(new LogProxyHandler()).newProxyInstance(new UserServiceImpl());
		service.add();
		createProxyClassFile();
	}
	/**
	 * 生成代理类文件
	 */
	public static void createProxyClassFile() {
		@SuppressWarnings("restriction")
		byte[] data = ProxyGenerator.generateProxyClass("$Proxy1",new Class[]{Service.class});
		//字节数组通过流的形式保存项目文件
		try {
			FileOutputStream out=new  FileOutputStream("$Proxy1.class");
			out.write(data);
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

反编译生成的代理文件:

import cn.rjx.tq.sproxy.Service;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy1
  extends Proxy
  implements Service
{
  private static Method m1;
  private static Method m5;
  private static Method m2;
  private static Method m3;
  private static Method m6;
  private static Method m0;
  private static Method m4;
  
  public $Proxy1(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 query()
    throws 
  {
    try
    {
      this.h.invoke(this, m5, 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 void add()
    throws 
  {
    try
    {
      this.h.invoke(this, m3, null);
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final void del()
    throws 
  {
    try
    {
      this.h.invoke(this, m6, null);
      return;
    }
    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);
    }
  }
  
  public final void update()
    throws 
  {
    try
    {
      this.h.invoke(this, m4, null);
      return;
    }
    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") });
      m5 = Class.forName("cn.rjx.tq.sproxy.Service").getMethod("query", new Class[0]);
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      m3 = Class.forName("cn.rjx.tq.sproxy.Service").getMethod("add", new Class[0]);
      m6 = Class.forName("cn.rjx.tq.sproxy.Service").getMethod("del", new Class[0]);
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      m4 = Class.forName("cn.rjx.tq.sproxy.Service").getMethod("update", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }
}

可以看出jdk动态代理在运行时生成一个代理类文件。通过我们传入的InvocationHandler实例,由代理类实例调用invoke().

感觉动态代理是将(A*C+B*C)转换成(A+B)*C,A,B为用户核心代码,C为方法执行前后的相同操作,比如日志管理,权限管理等。这就是AOP的基本思想吧。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值