代理模式
所谓代理,就是一个人或者机构代表另一个人或者机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口或者抽象类,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
按照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。
静态代理实例,假设现在需要一个回唱歌跳舞的演员,此时我们就联系他们的经纪人(代理),通过经纪人完成。
首先创建一个代理类和委托类共同的接口Human:
package Proxy01;
public interface Human {
void sing(float money);
void dance(float money);
void eat();
}
接着分别创建代理类和委托类实现这两个接口:
package Proxy01;
public class SpringBrother implements Human {//委托类
public void sing(float money) {
System.out.println("拿到钱"+money+"开始唱歌!");
}
public void dance(float money) {
System.out.println("拿到钱"+money+"开始跳舞!");
}
public void eat() {
System.out.println("开始吃饭!");
}
}
package Proxy01;
public class MiddleMan implements Human {//代理类
private Human h;
public MiddleMan(Human h) {
super();
this.h = h;
}
public void sing(float money) {
h.sing(money);
}
public void dance(float money) {
h.dance(money);
}
public void eat() {
}
}
测试类
package Proxy01;
public class Main {
public static void main(String[] args) {
Human actor=new SpringBrother();
Human middleman=new MiddleMan(actor);
middleman.sing(100);
middleman.dance(2000);
}
}
以上是实现接口的,同样也可以是继承抽象类:
创建代理类和委托类共同的抽象类Human:
package Proxy02;
public abstract class Human {
public abstract void sing(float money);
public abstract void dance(float money);
public abstract void eat();
}
创建代理类和委托类继承抽象类:
package Proxy02;
public class SpringBrother extends Human {
public void sing(float money) {
System.out.println("拿到钱"+money+"开始唱歌!");
}
public void dance(float money) {
// TODO Auto-generated method stub
System.out.println("拿到钱"+money+"开始跳舞!");
}
public void eat() {
// TODO Auto-generated method stub
System.out.println("开始吃饭!");
}
}
package Proxy02;
public class MiddleMan extends Human {//代理类
SpringBrother h=new SpringBrother();
public void sing(float money) {
h.sing(money);
}
public void dance(float money) {
h.dance(money);
}
public void eat() {
}
}
测试类:
package Proxy02;
public class Main {
public static void main(String[] args) {
Human middleman=new MiddleMan();
middleman.sing(100);
middleman.dance(2000);
}
}
以上两个例子的结果都为:拿到钱100.0开始唱歌,拿到钱2000.0开始跳舞。
动态代理实例
没有写代理类
基于接口的动态代理
被代理对象的类至少实现一个接口
基于子类的动态代理
要借助第三方CGLIB
基于接口的动态代理
首先要创建一个接口。
package Proxy01;
public interface Human {
void sing(float money);
void dance(float money);
void eat();
}
package Proxy03;
public class SpringBrother implements Human{
public void sing(float money) {
System.out.println("拿到钱"+money+"开始唱歌!");
}
public void dance(float money) {
// TODO Auto-generated method stub
System.out.println("拿到钱"+money+"开始跳舞!");
}
public void eat() {
// TODO Auto-generated method stub
System.out.println("开始吃饭!");
}
}
package Proxy01;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
Human actor=new SpringBrother();
/*
* ClassLoader loader:类加载器。固定写法:代理人用相同的类加载器即可
* Interface[] interfaces:代理对象要实现的接口。固定写法。和被代理人相同即可。
* InvocationHander h :接口。如何代理,策略设计模式。
*/
Human middleman=(Human)Proxy.newProxyInstance(actor.getClass().getClassLoader(),actor.getClass().getInterfaces(),new InvocationHandler() {
@Override
//匿名内部类,具体策略
//只要执行任何方法,都会经过该方法
/*返回值:调用函数的返回值
* Object arg0:当前代理对象的引用。不是程序员使用的。
* Method arg1:当前执行的方法
* Object[] arg2:当前执行方法需要的参数
*/
public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
// TODO Auto-generated method stub
if ("sing".equals(arg1.getName()))
{
float money=(float)arg2[0];
if(money>1000)
{
arg1.invoke(actor, money/2);
}
}
if ("dance".equals(arg1.getName()))
{
float money=(float)arg2[0];
if(money>500)
{
arg1.invoke(actor, money/2);
}
}
return null;
}
});
middleman.sing(1000);
middleman.dance(2000);
}
}
当被代理对象的类一个接口都没有实现,此时就应该用基于子类的动态代理,要用到第三方jar包cglib。
package Proxy03;
public class SpringBrother{
public void sing(float money) {
System.out.println("拿到钱"+money+"开始唱歌!");
}
public void dance(float money) {
// TODO Auto-generated method stub
System.out.println("拿到钱"+money+"开始跳舞!");
}
public void eat() {
// TODO Auto-generated method stub
System.out.println("开始吃饭!");
}
}
package Proxy03;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class Main {
public static void main(String[] args) {
/*
* Class superclass:父类型
* Callback callback:如何代理
*/
SpringBrother actor=new SpringBrother();//类不能是final修饰
SpringBrother middleman=(SpringBrother) Enhancer.create(SpringBrother.class,new MethodInterceptor() {
//匿名内部类,具体策略
//只要执行任何方法,都会经过该方法
/*返回值:调用函数的返回值
* Object arg0:当前代理对象的引用。不是程序员使用的。
* Method arg1:当前执行的方法
* Object[] arg2:当前执行方法需要的参数
*/
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
// TODO Auto-generated method stub
if ("sing".equals(arg1.getName()))
{
float money=(float)arg2[0];
if(money>1000)
{
arg1.invoke(actor, money/2);
}
}
if ("dance".equals(arg1.getName()))
{
float money=(float)arg2[0];
if(money>500)
{
arg1.invoke(actor, money/2);
}
}
return null;
}
});
middleman.sing(100);
middleman.dance(2000);
}
}