代理模式是经常使用的java设计模式,他的特征是代理类与目标类有相同的接口。代理类主要负责为目标类预处理消息、过滤消息、把消息转发给目标类,以及事后处理消息等。

代理类与目标类之间一般会存在关联关系。一个代理类的对象与一个目标类的对象关联。代理类的对象本身并不真正实现服务,而是通过调用目标类的对象的相关方法。来提供特定的服务。

        结构图例如以下:

               代理模式(静态代理+动态代理)——JAVA_代理类

        依照代理的创建时期。代理类能够分为静态代理和动态代理。

 

        静态代理:由程序猿创建或特定工具自己主动生成源码,再对其编译。在程序执行前,代理类(Proxy)的.class文件就已经存在了。 

        动态代理:在程序执行时。运用反射机制动态创建代理类(Proxy)而成。

静态代理:


调用步骤例如以下:


            代理模式(静态代理+动态代理)——JAVA_静态代理_02


实例:


UserManager接口



package ZhuDan.Test;

public interface UserManager {
public void addUser(String UserId,String UserName);
public void queryUser(String UserId);
}

UserManagerImpl目标类实现UserManager接口:


package ZhuDan.Test;

public class UserManagerImpl implements UserManager {

public void addUser(String UserId,String UserName) {
System.out.println("用户ID:"+UserId);
System.out.println("username:"+UserName);
}

public void queryUser(String UserId){
System.out.println("用户ID:"+UserId);
}
}

UserManagerImplProxy代理类实现UserManager接口:

package ZhuDan.Test;

public class UserManagerImplProxy implements UserManager {

private UserManager userManager;
public UserManagerImplProxy(UserManager userManager){
this.userManager=userManager;
}
public void addUser(String UserId,String UserName) {
try{
System.out.println("~~~~~~~~~~addUser開始运行~~~~~~~~~~~");
userManager.addUser( UserId,UserName);
}catch(Exception e){
e.printStackTrace();
System.out.print("~~~~~~~~~~addUser运行出错~~~~~~~~~~~");
}finally{
System.out.print("~~~~~~~~~~addUser成功运行~~~~~~~~~~~");
}
}

public void queryUser(String UserId){
try{
System.out.println("~~~~~~~~~~queryUser開始运行~~~~~~~~~~~");
userManager.queryUser( UserId);
}catch(Exception e){
e.printStackTrace();
System.out.print("~~~~~~~~~~queryUser运行出错~~~~~~~~~~~");
}finally{
System.out.print("~~~~~~~~~~queryUser成功运行~~~~~~~~~~~");
}
}
}


Manager类:



package ZhuDan.Test;

public class Manager {
public static void main(String args[]){
UserManager userManager=new UserManagerImplProxy(new UserManagerImpl());
userManager.addUser("0001", "张三");
userManager.queryUser("0001");
}
}

打印结果:

       代理模式(静态代理+动态代理)——JAVA_动态代理_03 


分析静态代理:


      从上面的样例能够看到,每一个代理类都仅仅能为一个接口服务,这样一来。进行程序开发时必然会产生大量的类。并且。所有的代理操作除了调用的方法不一样之外,其它的操作都一样,这样就有非常多的反复性代码。

那么应该怎样解决问题呢?这一问题最好的解决方案是能够通过一个代理类来完毕所有的代理功能,这也就是动态代理。


动态代理:


流程图例如以下:


       代理模式(静态代理+动态代理)——JAVA_代理类_04


UserManager接口:



package ZhuDan.Test;

public interface UserManager {
public void FindUserById(String UserId);
public void addUser(String UserId,String UserName);
}

UserManagerImpl目标类实现UserManager接口:


package ZhuDan.Test;

public class UserManagerImpl implements UserManager {

public void addUser(String UserId,String UserName) {
System.out.println("用户ID:"+UserId);
System.out.println("username:"+UserName);
}

public void FindUserById(String UserId){
System.out.println("用户ID:"+UserId);
}
}

UserManagerImplProxy代理类实现InvocationHandler接口:


package ZhuDan.Test1;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class UserManageProxy implements InvocationHandler {

private Object target;
/**
* 绑定托付对象并返回一个代理类
* @param target
* @return
*/
public Object bind(Object target) {
//目标
this.target = target;
ClassLoader str= target.getClass().getClassLoader();
//取得代理对象
//newProxyInstance三个參数:代理类的装载器、接口、指派方法调用的调用处理程序
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
//args:包装全部參数
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result=null;
System.out.println("~~~~~~~~~~"+method.getName()+" 開始运行~~~~~~~~~~~");
//取得參数
for(int i=0;i<args.length;i++){
System.out.println("《~~~~~~~~~~參数为:"+args[i]+"~~~~~~~~~~~》");
}
try{
//运行方法 ,加入方法就是target。args是參数
result=method.invoke(target, args);
System.out.println("~~~~~~~~~~"+method.getName()+" 成功运行~~~~~~~~~~~");
}catch(Exception e){
e.printStackTrace();
System.out.print("~~~~~~~~~~"+method.getName()+"运行出错~~~~~~~~~~~");
}
return result;
}
}

Manager类:


package ZhuDan.Test1;

public class Manager {
public static void main(String args[]){
UserManageProxy userManagerProxy=new UserManageProxy();
UserManager userManager=(UserManager)userManagerProxy.bind(new UserManagerImpl());
userManager.FindUserById("0001");
userManager.addUser("0001", "张三");
}
}

输出结果:

       代理模式(静态代理+动态代理)——JAVA_程序猿_05

分析:


         动态代理的实现包括一个类和一个接口: 


 InvocationHandler接口: 

        public interface InvocationHandler { 

               public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; 

         } 

       參数说明: 

              Object proxy:指被代理的对象。 

              Method method:要调用的方法 

              Object[] args:方法调用时所含的參数 

Proxy类: 

         Proxy类是专门完毕代理的操作类。能够通过此类为一个或多个接口动态地生成实现类,提供了例如以下的操作方法: 

         public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,  InvocationHandler h) throws IllegalArgumentException 

         參数说明: 

                 ClassLoader loader:类载入器,代理类和目标类为同一个载入器。

                 Class<?

>[] interfaces:得到目标类的全部接口 

                 InvocationHandler h:得到InvocationHandler接口的子类实例,即代理类(UserManagerImplProxy)

总结:

        动态代理类的字节码在程序执行时由Java反射机制动态生成。无需程序猿手工编写它的源码。

动态代理类简化了编程工作。并且提高了软件系统的可扩展性,由于Java 反射机制能够生成随意类型的动态代理类,而java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。