Java代理模式总结及案例

1.静态代理

1.代理模式

实现原理:代理类和真实类都实现同一个接口,实际还是依赖真实类去实现功能

1.1代理模式代码

package com.amarsoft.designmode.proxy;

/**
 * 代理模式:提供一个统一的接口,具体的实现类和代理类都实现该接口,用于代理类可以完成具体类相同的方法
 * @author amarsoft
 *
 */
public interface Subject {
	//统一的方法
	void request();
}

----------------------------------------------------
package com.amarsoft.designmode.proxy;
/**
 * 代理类
 * @author 小虾
 */
public class Proxy implements Subject{
	//被代理的类
	public RealSubject subject ;

	@Override
	public void request() {
		System.out.println("proxy implements ways...");
		if(subject ==null) {
			subject = new RealSubject();
		}
		//调用真实类中的方法
		subject.request();
	}
	
}

--------------------------------------------------------
package com.amarsoft.designmode.proxy;
/**
 * 真实类
 * @author 小虾
 *
 */
public class RealSubject implements Subject {

	@Override
	public void request() {
		System.out.println("realSubject implements ways ...");
	}
}
------------------------------------------
package com.amarsoft.designmode.proxy;

/**
 * designmode
 * 代理的主入口测试类
 * @author amarsoft
 * 静态代理:需要自己去实现代理类。
 *
 */
public class ProxyMain {
	
	public static void main(String[] args) {
		Subject proxy = new Proxy();
		proxy.request();
	}

}

1.2代理模式案例

案例:通过中介买房

1.2.1案例代码

package com.amarsoft.designmode.proxy.demo;
/**
 * 买房接口
 * @author 小虾
 */
public interface BuyHouseInterface {
	
	void buy();

}

------------------------------------------------
package com.amarsoft.designmode.proxy.demo;
/**
 * 真实买房对象
 * @author 小虾
 *
 */
public class SubjectBuyHouse implements BuyHouseInterface{

	@Override
	public void buy() {
		System.out.println("我自己在成都买房");
	}

}
------------------------------------------
package com.amarsoft.designmode.proxy.demo;
/**
 * 代理购房:实际调用具体购房者的买房方法
 * @author 
 *
 */
public class ProxyBuyHouse implements BuyHouseInterface{
	//具体的买房的人
	private SubjectBuyHouse buyHoser ;
	
	public ProxyBuyHouse(SubjectBuyHouse buyHoser) {
		this.buyHoser = buyHoser;
	}

	@Override
	public void buy() {
		System.out.println("中介帮忙买房子赚差价");
		buyHoser.buy();
		System.out.println("中介成功赚取差价");
	}
	
	public static void main(String[] args) {
		ProxyBuyHouse proxy = new ProxyBuyHouse(new SubjectBuyHouse());
		proxy.buy();
	}
}
//运行结果
中介帮忙买房子赚差价
	我自己在成都买房
中介成功赚取差价

1.3 静态代理总结

实际上,真正的功能还是有真实的目标类来实现的,代理类扩展争强目标类的行为

二.动态代理

2.1 JDK动态代理

  1. 实现invocationHandle,重写invoke();
package com.amarsoft.designmode.proxy.jdkproxy;

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

import com.amarsoft.designmode.proxy.demo.BuyHouseInterface;
import com.amarsoft.designmode.proxy.demo.SubjectBuyHouse;

/**
* 
* jdk 的动态代理:
* @author 
*
*/
public class JDKProxy implements InvocationHandler{
   //被代理的类
   public Object tarjet ;
   
   public JDKProxy(Object tarjet) {
   	this.tarjet = tarjet;
   }

   @Override
   public Object invoke(Object proxy, Method method, Object[] objs) throws Throwable {
   	System.out.println("中介自动代理买房");
   	Object invoke = method.invoke(tarjet, objs);
   	System.out.println("中介自动代理买房成功");
   	return invoke;
   }
   
   
   public static void main(String[] args) {
   	//需要被代理的类
   	SubjectBuyHouse sbh = new SubjectBuyHouse();
   	JDKProxy proxyBuyHouse = new JDKProxy(sbh);
   	//参数:需要被代理的类的 类加载器,class和代理 类InvocationHandler
   	BuyHouseInterface buy = (BuyHouseInterface) Proxy.newProxyInstance(sbh.getClass().getClassLoader(),
   			sbh.getClass().getInterfaces(), proxyBuyHouse);
   	buy.buy();		
   }
}
//运行结果:
/**
    * 中介自动代理买房
           我自己在成都买房
           中介自动代理买房成功	
    */

动态代理:
为接口创建代理类的字节码文件,使用ClassLoader将字节码文件加载到JVM;创建代理类实例对象,执行对象的目标方法;

2.2cglib动态代理

2.2.1案例

package spring.cglib.demo;

/**
 * 具体的买房客户类
 * @author 小虾
 *
 */
public class SubjectCustomer {
	//买房
	public void buy(){
		System.out.println("我是买房客户,自己在成都买房");
	}
	//租房
	public void rent(){
		System.out.println("我是[租房]客户,自己在成都租房");
	}
	
}

--------------------------------------------------------------------

package spring.cglib.demo;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
/**
 * 租房
 * @author 小虾
 *
 */
public class RentHouseProxy implements MethodInterceptor {
	//需要被代理的类
	private Object obj ; 
	
	public RentHouseProxy(Object obj) {
		this.obj = obj;
	}

	@Override
	public Object intercept(Object o, Method method, Object[] args,
			MethodProxy methodProxy) throws Throwable {
		//invoke:被代理的类,外部传入的;args:参数
		System.out.println("我是[租房]代理");
		Object object = methodProxy.invoke(obj, args);
		return object;
	}

}

----------------------------------------

package spring.cglib.demo;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

/**
 * @author 小虾
 *
 */
public class BuyHouseProxy implements MethodInterceptor{

	@Override
	public Object intercept(Object obj, Method method, Object[] args,
			MethodProxy methodProxy) throws Throwable {
		System.out.println("我是买房代理");
		Object object = methodProxy.invokeSuper(obj, args);
		return object;
	}

}

----------------------------------------------------------------------

package spring.cglib.demo;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.CallbackFilter;
import org.springframework.cglib.proxy.Enhancer;
/**
 * cglib 租房买房 多映射类
 * @author 小虾
 *
 */
public class CgilbHouseTest {
	
	public static void main(String[] args) {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(SubjectCustomer.class);
		SubjectCustomer customer = new SubjectCustomer();
		//callback 只有一个参数
		//enhancer.setCallback(new BuyHouse());
		// callback 有多个参数 :租房;买房
		enhancer.setCallbacks(new Callback [] {new BuyHouseProxy(),new RentHouseProxy(customer)});
		enhancer.setCallbackFilter(new CallbackFilter() {
			//通过方法区分调用某个类
			@Override
			public int accept(Method method) {
				if(method.getName().equals("rent")){
					return 1 ;
				}else{
					return 0;
				}
				
			}
		});
		
		//调用动态代理的方法
		SubjectCustomer customerProxy = (SubjectCustomer)enhancer.create();
		customerProxy.rent();
		customerProxy.buy();
	}

}

2.2.2 cglib动态代理总结

  1. 实现MethodInterceptor,重写intercept();
  2. intercept()有两个方法,invoke(“传入的被代理的类”,参数)和invokeSuper(“intercept中的object”,参数),两个方法上面案例中都有使用,可以具体参考上面案例。
  3. Enhancer 可以有根据方法名称,有多个回调。setCallbacks()配合setCallbackFilter(),可以调用不同的代理类.

JDK和cglib动态代理区别

  1. java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理;cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理
  2. JDK动态代理只能对实现了接口的类生成代理;CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
结束:

快过年了,祝各位都事事顺利。有问题的帮忙指正。

你可能感兴趣的:(Java代理模式总结及案例)