理解代理和动态代理模式

Java的动态代理是实现Spring AOP的底层技术,所以有必要理解一下。从代理开始过度到动态代理。
====================================================================================
package com.nange.generalproxy;

/**
 * 一般的代理模式
 * 为什么要使用代理,根本原因当然是为了减少重复代码。
 * 举个实际的例子:像卖电脑这样一件事情,有很多的电脑生成厂商,他们卖出去电脑,
 * 都需要前期的宣传营销,然后把各自的电脑卖出去,然后都需要售后服务。
 * 而宣传营销和售后服务对于每一个厂商来说都是一样的(大致可以这样理解),只有各自生成的电脑不一样。
 * 为了节约成本,就产生了代理这样一个东西,每一个电脑生成厂商都把宣传营销和售后服务交给他们的代理去完成,
 * 电脑生产商只关心生成就可以了,这样可以极大的提高效率,和节约成本。
 * 在实际的软件开发过程中,像性能监控和事务管理,也是同样的道理。
 * 下面是一个模拟过程:最终目的是卖出去电脑,原来是由各电脑生成商卖,现在改为代理来卖。
 * @author nange
 * @version 1.0
 */
public class Main {
/**
 * 这样一个代理就可以代理任意多个电脑商了
 */
public static void main(String[] args) {
SellComputer producer1 = new Lenovo();
SellComputer producer2 = new Asus();
//代理producer1卖电脑
SellComputer proxy = new ComputerProxyer(producer1);
proxy.sellComputer("联想");
//代理producer2卖电脑
proxy = new ComputerProxyer(producer2);
proxy.sellComputer("华硕");
}

}

package com.nange.generalproxy;

/**
 * 卖电脑接口,因为每个电脑商最终都是想卖出自己的电脑,所以各个生产商都实现这个接口
 * @author nange
 * @version 1.0
 */
public interface SellComputer {
void sellComputer(String brand);

}

package com.nange.generalproxy;

public class Lenovo implements SellComputer {
@Override
public void sellComputer(String brand) {
System.out.println(brand + "电脑卖出");
}

}

package com.nange.generalproxy;

public class Asus implements SellComputer {
@Override
public void sellComputer(String brand) {
System.out.println(brand + "电脑卖出");
}

}

package com.nange.generalproxy;

/**
 * 作为电脑商的代理
 * @author nange
 * @version 1.0
 */
class ComputerProxyer implements SellComputer {
private SellComputer sell;
public ComputerProxyer(SellComputer sell) {
this.sell = sell;
}
@Override
public void sellComputer(String brand) {
System.out.println("宣传营销");
sell.sellComputer(brand);
System.out.println("售后服务");
}

}

========================================================================================
package com.nange.dynamicproxy;

import java.lang.reflect.Proxy;

import com.nange.generalproxy.Asus;
import com.nange.generalproxy.Lenovo;
import com.nange.generalproxy.SellComputer;

/**
 * 动态代理模式
 * 一般的代理模式已经很好的解决了代码重复的问题,但是人总是不满足的,要是代理可以让程序帮我们生成该多好。
 * 在JDK1.3以后,Java提供了动态代理技术,允许开发者在运行期创建接口的代理实例。
 * 动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。
 * 其中InvocationHandler是一个接口,可以通过实现该接口定义代理逻辑,并通过反射机制调用目标类的代码,动态的
 * 将代理逻辑和业务逻辑组合在一起。而Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的
 * 代理对象。
 * 还是用上面的卖电脑的例子,把之前的代理模式换作动态代理模式。
 * @author nange
 * @version 1.0
 */
public class Main {
/**
 * 这样就不用编写代理类了,不过还是写了一个ComputerHandler类,可以使用匿名内部类的方式就不用写这个类了,
 * 不过需要把producer1这类的变量定义为final类型,因为匿名内部类只能引用外部类为final的变量
 */
public static void main(String[] args) {
SellComputer producer1 = new Lenovo();
SellComputer producer2 = new Asus();
ComputerHandler handler1 = new ComputerHandler(producer1);
ComputerHandler handler2 = new ComputerHandler(producer2);
/**
 * Proxy.newProxyInstance()方法有三个参数,
 * 第一个参数为类加载器,
 * 第二个参数为创建代理实例所需要实现的一组接口,
 * 第三个参数为整合了业务逻辑和代理逻辑的组合对象,必须实现InvocationHandler接口
 */
SellComputer proxy = (SellComputer)Proxy.newProxyInstance(producer1.getClass().getClassLoader(), 
producer1.getClass().getInterfaces(), handler1);
proxy.sellComputer("联想");
proxy = (SellComputer)Proxy.newProxyInstance(producer2.getClass().getClassLoader(), 
producer2.getClass().getInterfaces(), handler2);
proxy.sellComputer("华硕");

}

}

package com.nange.dynamicproxy;

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

import com.nange.generalproxy.SellComputer;

class ComputerHandler implements InvocationHandler {
private SellComputer target;
public ComputerHandler(SellComputer sell) {
this.target = sell;
}
/**
 * proxy是最终生成的代理实例,一般用不到;
 * method是被代理目标实例的某个具体方法,通过它可以发起目标实例方法的反射调用;
 * args是传给被代理实例某一个方法的入参数组,在方法反射调用时使用。
 */
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("宣传营销");
Object obj = method.invoke(target, args);
System.out.println("售后服务");
return obj;
}

}

你可能感兴趣的:(理解代理和动态代理模式)