静态代理 & 动态代理

代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。值得注意的是,代理类和被代理类应该共同实现一个接口,或者是共同继承某个类。

静态代理就是用接口实现向上转型,通过实现类重写方法实现代理增强

// 定义接口
public interface IAnimal {
    void eat();
}

/**
 * 目标对象实现了某一个接口
 */
public class Cat implements IAnimal {

    @Override
    public void eat() {
        System.out.println("小猫爱吃鱼");
    }
}

/**
 * 静态代理
 * 代理对象和目标对象实现相同的接口
 */
public class AnimalProxy implements IAnimal {

    //使用接口对象 接收目标对象
    private IAnimal target;

    public AnimalProxy(IAnimal target) {
        this.target = target;
    }

    // 对对象的 eat() 方法进行功能扩展, 代理增强
    @Override
    public void eat() {
        System.out.println("小猫是一只布偶哦!");
        target.eat();
    }

    //测试使用
    public static void main(String[] args) {
        //目标对象
        IAnimal target = new Cat();

        //代理对象
        IAnimal proxy = new AnimalProxy(target);

        // 执行代理的方法
        proxy.eat();

    }
}

运行结果:

 

 

 

动态代理,通过反射机制,运行时创建代理类,

/**
 *  JDK动态代理   使用反射机制
 *  动态代理不需要实现接口,但需要指定接口类型
 */
public class DynamicProxy {

    //维护一个目标对象
    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    public Object  getProxyInstance() {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     * @param proxy         代理者,如果想对代理者做一些操作可以使用这个参数
                     * @param method        被执行的方法,
                     * @param args          执行该方法所需要的参数
                     * @return
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("before method excute!");
                        System.out.println("but i love dog more!");
                        //1. 传入的对象通过反射获取数据
                        Object resObj = method.invoke(target, args);
                        System.out.println("after method excute!");
                        return resObj;
                    }
                }
        );
    }

    public static void main(String[] args) {
        IAnimal cat = new Cat();
        IAnimal iAnimal = (IAnimal) new DynamicProxy(cat).getProxyInstance();
        iAnimal.eat();

    }

}

 

 

 

 

public class DynamicProxy1 implements InvocationHandler {
    private Object target;

    public DynamicProxy1(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before method excute !");
        Object obj = method.invoke(target, args);
        System.out.println("after method excute !");
        return null;

    }

    public static void main(String[] args) {

        System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

        IAnimal cat = new Cat();
        DynamicProxy1 handle = new DynamicProxy1(cat);
        IAnimal iAnimal = (IAnimal) Proxy.newProxyInstance(cat.getClass().getClassLoader(), cat.getClass().getInterfaces(), handle);
        iAnimal.eat();
    }
}

 

 

 

上面为代理实现一个接口的情况, 如果此时还有一个宠物医院的接口(不同接口),需要给小猫治病,此时,如果使用静态代理, 则需要手动编写一个医院代理类,然后进行代理处理,以此方式,如果有N多个接口需要进行代理处理,则需要些N多个代理类,代码量庞大; 动态代理则可已解决此问题,根据传入的对象进行反射,可拿到不同的需要代理的对象,执行方法。

例如:

// 宠物医院接口
public interface IAnimalHospital {
    // 医院治疗方法
    void care();
}


/**
 * 需要代理的对象, 小猫宠物医院,实现方法对小猫进行治疗
 */
public class CatHospital implements IAnimalHospital{
    @Override
    public void care() {
        System.out.println("给小猫进行治疗");
    }
}

/**
 *  JDK动态代理   使用反射机制
 *  动态代理不需要实现接口,但需要指定接口类型
 */
public class DynamicProxy {

    //维护一个目标对象
    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    public Object  getProxyInstance() {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     * @param proxy         代理者,如果想对代理者做一些操作可以使用这个参数
                     * @param method        被执行的方法,
                     * @param args          执行该方法所需要的参数
                     * @return
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("before method excute!");
                        System.out.println("but i love dog more!");
                        //1. 传入的对象通过反射获取数据
                        Object resObj = method.invoke(target, args);
                        System.out.println("after method excute!");
                        return resObj;
                    }
                }
        );
    }

    public static void main(String[] args) {
        IAnimal cat = new Cat();
        IAnimal iAnimal = (IAnimal) new DynamicProxy(cat).getProxyInstance();
        iAnimal.eat();

        IAnimalHospital careCat = new CatHospital();
        IAnimalHospital iAnimalHospital = (IAnimalHospital) new DynamicProxy(careCat).getProxyInstance();
        iAnimalHospital.care();

    }

}

 

 

 

个人理解,如有错误,烦请指正

posted @ 2021-12-28 00:10  长弓射大狗  阅读(28)  评论(0)    收藏  举报