聊聊代理模式

1.什么是代理模式

其实代理模式顾名思义就是使用一个代理类来代替原对象,来进行一些操作。

2.生活中的代理

譬如刚毕业的小菜,去北京,刚去自己找房子租很困难,要不价格太贵,要不就是很便宜环境不太好,总是没顺心的,便会给中介打电话,这样中介就会帮小菜去找房子,因为中介掌握房源的信息很多很全面,这样找房子的活就由中介代理小菜去找了。这就是一个代理的过程。

3.java中的代理有哪些

静态代理动态代理cglib代理

4.静态代理分析

关键: 代理对象,要实现与目标对象一样的接口

实现:

小菜学生类:

public class XiaoCai implements IHouseFunction{

	@Override
	public void getApartmentAbility() {
		// TODO Auto-generated method stub
		System.out.println("------得到房子------");
	}
}
搞到房子的技能接口:

//租房子接口
public interface IHouseFunction {
	//租到房子的技能
	public void getApartmentAbility();
}
房东类(代理类):

//房东类同样也可以叫做代理类
public class Landlord implements IHouseFunction{
	private IHouseFunction houseFunction;

	//通过构造器传入目标对象
	public Landlord(IHouseFunction houseFunction) {
		this.houseFunction = houseFunction;
	}

	public void setHouseFunction(IHouseFunction houseFunction) {
		this.houseFunction = houseFunction;
	}

	@Override
	public void getApartmentAbility() {
		// TODO Auto-generated method stub
		System.out.println("房东开始给小菜找房子了。。。。");
		houseFunction.getApartmentAbility();
		System.out.println("房东已经帮小菜找到房子了。。。。");
	}
	
}
测试类:

public class Test {
	public static void main(String[] args) {
		IHouseFunction houseFunction =new XiaoCai();
		Landlord landlord =new Landlord(houseFunction);
		//从调用房东技能可以看出,房子是代理搞到的
		landlord.getApartmentAbility();
	}
}
结果:

聊聊代理模式_第1张图片

总结:

静态代理的优点:可以做到不修改目标对象功能的前提下,对目标对象实现了扩展,遵循了开闭原则。

静态代理的缺点:由于静态代理其本身的特点,代理类和目标对象实现同一个接口,同时这也是一个缺点,如果目标对象需要增加更多,那么需要增加更多的代理类。同时接口也在增加更多,都需要维护,这样很麻烦。所以可以利用之前博文中的工厂模式,增加对象,哈哈。而这种策略就被叫做动态代理(或者叫JDK代理)。

5.动态代理(或者叫JDK代理)分析

关键:代理类不用实现接口,而代理类对象是通过JDK生成的,动态的在内存中构建代理对象(想想也知道这东西肯定不会凭空产生),所以同时需要传入目标对象,以及实现的接口,剩下的jdk帮我们去做了。哈哈

实现:

小菜学生类:

public class XiaoCai implements IHouseFunction{

	@Override
	public void getApartmentAbility() {
		// TODO Auto-generated method stub
		System.out.println("------得到房子------");
	}
}
搞到房子的技能接口:

//租房子接口
public interface IHouseFunction {
	//租到房子的技能
	public void getApartmentAbility();
}
房东类(代理类):

//房东类同样也可以叫做代理类
public class Landlord {
	//定义目标对象
	private Object target;
	//还是通过构造器传入
	public Landlord(Object target) {
		super();
		this.target = target;
	}
	
	public Object getProxyInstance(){
		return Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(), 
				new InvocationHandler() {
					
					@Override
					public Object invoke(Object proxy, Method method, Object[] arg2)
							throws Throwable {
						System.out.println("房东开始给小菜找房子了。。。。");
						Object retValue =method.invoke(target, arg2);
						System.out.println("房东已经帮小菜找到房子了。。。。");
						return retValue;
					}
				});
	}
}
测试类:

public class Test {
	public static void main(String[] args) {
		IHouseFunction target =new XiaoCai();
		IHouseFunction houseFunction =(IHouseFunction) new Landlord(target).getProxyInstance();
		houseFunction.getApartmentAbility();
		System.out.println("目标对象:"+target.getClass());
		System.out.println("代理对象:"+houseFunction.getClass());
	}
}
结果:

聊聊代理模式_第2张图片

总结:

动态代理的优点:代理对象不需要实现接口。

动态代理的缺点:目标对象却仍然需要实现接口。如果我需要一个目标对象扩展功能,但是却没有实现目标接口,动态代理又玩不转了。我们可以使用子类实现对目标对象的扩展,这种方式叫cglib代理(或者叫做子类代理)。

6.cglib代理分析

关键:cglib是在运行期扩展java类与实现java接口。cglib包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。

实现:

小菜学生类:

public class XiaoCai {

	public void getApartmentAbility() {
		// TODO Auto-generated method stub
		System.out.println("------得到房子------");
	}
}
房东类(代理类):

//房东类同样也可以叫做代理类
public class Landlord implements MethodInterceptor{

	//维护一个目标对象
	private Object target;
	public Landlord(Object target) {
		this.target =target;
	}
	//给目标对象创建代理对象
	public Object getProxyInstance(){
		Enhancer en =new Enhancer();
		en.setSuperclass(target.getClass());
		en.setCallback(this);
		return en.create();
	}
	@Override
	public Object intercept(Object obj, Method method, Object[] arg2,
			MethodProxy proxy) throws Throwable {
		System.out.println("房东开始给小菜找房子了。。。。");
		Object retValue =method.invoke(target, arg2);
		System.out.println("房东已经帮小菜找到房子了。。。。");
		return retValue;
	}
	
}
测试类:

public class Test {
	public static void main(String[] args) {
		XiaoCai xiaoCaiTarget =new XiaoCai();
		XiaoCai xiaoCaiProxy =(XiaoCai) new Landlord(xiaoCaiTarget).getProxyInstance();
		xiaoCaiProxy.getApartmentAbility();
		System.out.println(xiaoCaiTarget.getClass());
		System.out.println(xiaoCaiProxy.getClass());
	}
}
结果:

聊聊代理模式_第3张图片

总结:

需要注意的是:cglib代理:需要引入 cglib – jar文件。但是spring的核心jar包已经包含了cglib功能。所以项目要引入spring的核心jar包,否则不可以使用cglib代理。引入jar包之后,就可以方便的在内存中动态的构建子类实现代理了。





你可能感兴趣的:(__8.1设计模式,java设计模式)