java之代理模式

静态代理:

 java代理是一种模式--代理模式。采用代理模式,可以在不改变目标类代码的基础上,通过代理对象,来增加额外的功能(比如增加日志检测等)或者只需要目标对象的部分行为。

java中,代理分为静态代理和动态代理。

静态代理:我的理解是程序员自己或者用某些工具去自己创建或者生成代理类。在使用之前,代理类已经存在。

动态代理:区别于静态代理,它是动态的,不需要程序员去自己创建,只需要采用现成的动态代理类库(jdk动态代理,cglib)调用某些类的某些方法,动态生成代理类。代理类在使用之前是不存在的。什么时候使用,什么时候创建。是动态的。

静态代理:

静态代理有两种实现方式。

1.合成

即将目标类作为代理类的全局成员。需要目标类实现接口

接口:

package com.wtd.staticproxy;

public interface Moveable {
    void move();
}

目标类:

package com.wtd.staticproxy;

import java.util.Random;

/**
 * @desc Car:被代理对象,真实对象
 * */
public class Car implements Moveable {

    @Override
    public void move() {
        try {
            System.out.println("the car is running");
            Thread.sleep(new Random().nextInt(1000));
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

代理类:

package com.wtd.staticproxy;

/**
 * @desc 静态代理 第二种方式:合成。
 * 静态代理,说白了,就是手动创建 代理类。手动创建的两种方式[继承,合成]
 * */
public class Car2 implements Moveable {//代理类:必须和被代理类都实现统一的接口
    Car car;//被代理类类 (真实类)
    public Car2(Car car) {
        super();
        this.car= car;
    }
    @Override
    public void move() {
        System.out.println("the car start");//业余方法
        long startTime= System.currentTimeMillis();//业余方法
        car.move();//调用被代理类的功能方法
        long endTime= System.currentTimeMillis();//业余方法
        System.out.println("the car stop,use time:"+ (endTime-startTime)+"ms");//业余方法
    }

}

测试类:

package com.wtd.staticproxy;

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Car car = new Car();//创建被代理类(真实类)
        Moveable m2= new Car2(car);//创建代理类
        m2.move();
    }

}

output:

the car start
the car is running
the car stop,use time:681ms

2.继承

代理类继承目标类。不需要目标类继承接口。但是目标类必须不能被final修饰

目标类:

package com.wtd.staticproxy;

import java.util.Random;

/**
 * @desc Car:被代理对象,真实对象
 * */
public class Car {

    public void move() {
        try {
            System.out.println("the car is running");
            Thread.sleep(new Random().nextInt(1000));
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

代理类:

package com.wtd.staticproxy;

/**
 * @desc 静态代理有两种方式, 这是第一种:继承的方式、
 * 第二种:合成
 * */
public class Car1 extends Car{
    @Override
    public void move() {
        System.out.println("汽车开始行驶");//业余方法
        long startTime= System.currentTimeMillis();//业余方法
        super.move();//调用父类的功能方法
        long endTime= System.currentTimeMillis();//业余方法
        System.out.println("汽车行驶结束,行驶了:"+ (endTime- startTime)+"毫秒");//业余方法
    }
}

测试类:

package com.wtd.staticproxy;

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Car m= new Car1();
        m.move();
    }

}

output:

the car start
the car is running
the car stop,use time:361ms

动态代理:

原理:类似于静态代理中的合成。被代理对象必须继承某一接口

接口:

package com.wtd.dynamicproxy3;

public interface Moveable {
    void move();
    void run(String args);
}

目标对象(被代理对象):

package com.wtd.dynamicproxy3;

public class Car implements Moveable {

    @Override
    public void move() {
        System.out.println("Car move()");
    }

    @Override
    public void run(String args) {
        System.out.println("Car run()"+ args);
    }

}

调用处理器对象:InvocationHandler对象

package com.wtd.dynamicproxy3;

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

public class LogHandler implements InvocationHandler {
    private Object proxied;
    public LogHandler(Object proxied) {
        this.proxied= proxied;
        // TODO Auto-generated constructor stub
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println(
            "----------proxy: "
            + proxy.getClass()
            + ", method: "
            + method+ ", args: "
            + args+ ", proxied: "
            + proxied.getClass());

        return method.invoke(proxied, args);
    }

}

测试类:

package com.wtd.dynamicproxy3;

import java.lang.reflect.Proxy;


public class TestDynamicProxy {
    public static void main(String[] args) {
        Car car= new Car();
        Moveable m= (Moveable) Proxy.newProxyInstance(Moveable.class.getClassLoader(), 
                new Class<?>[]{Moveable.class},
                new LogHandler(car));
        m.move();
        m.run("haha");
    }
}

output:

----------proxy: class com.sun.proxy.$Proxy0, method: public abstract void com.wtd.dynamicproxy3.Moveable.move(), args: null, proxied: class com.wtd.dynamicproxy3.Car
Car move()
----------proxy: class com.sun.proxy.$Proxy0, method: public abstract void com.wtd.dynamicproxy3.Moveable.run(java.lang.String), args: [Ljava.lang.Object;@5e743399, proxied: class com.wtd.dynamicproxy3.Car
Car run()haha

cglib动态代理:

原理:类似于静态代理中的继承方式。被代理对象的类不能被final所修饰

首先需要导入jar包:cglib-nodep-x.x.x.jar。可在mvnrepository下载。

被代理类:父类:realObject:

package com.wtd.cglibproxy;

/**
 * 目标类;父类;被代理类
 * 不能被final所修饰
 * */
public class Car {
    public void move() {
        System.out.println("the car running");
    }
}

方法拦截器类:

package com.wtd.cglibproxy;

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 CglibProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();
    
    /**
     * 设置获得代理对象(即子类对象)的方法
     * 需要用到 Enhancer
     * */
    public Object getProxy(Class clazz){
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }
    
    /**
     * @author WesTward
     * @param proxied:被代理对象,目标对象,父类对象
     * @param method: 目标对象的 方法
     * @param args: 目标对象的方法的参数
     * @param proxy: 代理对象
     * */
    @Override
    public Object intercept(Object proxied, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {
        System.out.println("Log---------start");
        proxy.invokeSuper(proxied, args);
        System.out.println("Log---------end");
        return null;
    }

}

测试类:

package com.wtd.cglibproxy;

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        CglibProxy cglibProxy= new CglibProxy();
        Car car = (Car) cglibProxy.getProxy(Car.class);
        car.move();
    }

}

output:

Log---------start
the car running
Log---------end

 附:

动态代理主要运用了java的反射机制。

原文地址:https://www.cnblogs.com/westward/p/5437120.html