java中静态代理模式与动态代理模式

静态代理与动态代理

静态代理

静态代理:特征是代理类和目标对象的类都是在编译期间确定下来,不利于程序的扩展。
同时,每一个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理,
最好可以通过一个代理类完成全部的代理功能。

动态代理

动态代理:
使用一个代理将对象包装起来,然后用该代理对象取代院士对象。任何对原始对象的调用都要通过代理,代理对象决定是否以及何时将
方法调用到原始对象上
动态代理是指客户通过代理类来调用其他对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象
动态代理的使用场合:
>调试
>远程方法调用
动态代理相比静态代理的优点:
抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理。这样,我们可以更加灵活和同一的处理众多的方法

静态代理的创建流程

创建接口

interface ClothFactory{

    void produceCloth();
}

创建代理类

注意点:
1.代理类中应当声明被代理类的对象
2.应当声明参数为被代理类对象的构造器

class ProxyClothFactory implements ClothFactory{

    private ClothFactory factory;//使用被代理类对象进行实例化

    public ProxyClothFactory(ClothFactory factory){
        this.factory = factory;
    }

    @Override
    public void produceCloth() {
        System.out.println("代理工厂准备工作");
        factory.produceCloth();
        System.out.println("代理工厂收尾工作");
    }
}

创建被代理类

class NikeClothFactory implements ClothFactory{


    @Override
    public void produceCloth() {
        System.out.println("Nike工厂生产一批衣服");
    }
}

方法的测试

public class StaticProxyTest {
public static void main(String[] args) {
//造被代理类对象
NikeClothFactory nk = new NikeClothFactory();
//造代理类
ProxyClothFactory pcf = new ProxyClothFactory(nk);
//调用方法
pcf.produceCloth();
}
}

输出结果:
代理工厂准备工作
Nike工厂生产一批衣服
代理工厂收尾工作

动态代理的创建流程

创建接口

interface Human{
    String getBelief();

    void eat(String food);
}

创建被代理类

class superMan implements Human{
    @Override
    public String getBelief() {
        return "I believe i can fly";
    }

    @Override
    public void eat(String food) {
        System.out.println("喜欢吃" + food);
    }
}

创建InvocationHandler的实现类

注意:
1.此类中声明的属性obj即为被代理类的对象
2.InvocationHandler中重写的invoke方法:当通过代理类的对象调用某个方法,就会直接调用如下的invoke方法
此方法中需要填入三个参数
>参数1:被代理类的对象。
>参数2:method代表的是代理类的对象调用的方法,因此要将被代理类要执行的方法声明在invoke方法中.
>参数3:反射中invoke方法需要提供的参数
3.method调用的invoke方法,此方法可以让参数1所提供的类调用method所代表的方法。

class myInvocationHandler implements InvocationHandler{

    private Object obj;//虽然声明为Object,但是赋值时需要使用被代理类的对象进行赋值
    public void bind(Object obj){
        this.obj = obj;
    }
    //当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法,invoke

    //当代理类的对象调用方法时,会自动调用handler中的方法,所以就需要将被代理类要执行的方法a的功能声明在invoke中
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        HumanUtil util = new HumanUtil();
        //参数一:代理类的对象。参数二;代理类的对象需要调用的方法。
        //此时method就是代理类对象调用的方法,此方法也就作为了被代理类对象瑶调用的方法
        //obj:被代理类的对象
        Object returnvalue =method.invoke(obj,args);
        //上述方法的返回值就作为当前类中invoke方法中的返回值
        return returnvalue;
    }


}

创建动态代理类

动态代理类主要用处是用来动态的创建被代理类的代理类对象
注意:
1.创建一个方法用来动态创建被代理类的对象
2.需要借助java.lang.reflect 包中的 Proxy 类的newProxyInstance方法
3.newProxyInstance:此方法中有三个参数
>参数1: 被代理类的加载器
>参数2:被代理类实现的接口
>参数3:InvocationHandler接口的实现类的对象
4.此类创建代理类之后,当代理类调用方法时,会自动调用InvocationHandler的实现类中重写的invoke方法。

class ProxyFactory{
  
    public static Object getProxyInstance(Object obj){//obj:被代理类的对象
        //创建invocationHandler的对象
        myInvocationHandler handler = new myInvocationHandler();
        //调用反射API下的类:Proxy
        //Proxy.newProxyInstance:创建一个代理类的对象。
        // 参数一:被代理类的加载器。参数二:接口。参数三:接口InvocationHandler的实现类
        handler.bind(obj);
        return  Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
    }
}

动态代理的测试

public class ProxyTest {
    public static void main(String[] args) {
        superMan superMan = new superMan();
        //创建了代理类对象
        Human supe =(Human) ProxyFactory.getProxyInstance(superMan);
        //当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法
        System.out.println(supe.getBelief());

        supe.eat("水果");

        System.out.println("*******************体现动态性*********");

        NikeClothFactory nikeClothFactory = new NikeClothFactory();
        //动态创建代理类的对象
        ClothFactory proxyInstance =(ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);

        proxyInstance.produceCloth();
    }
}

输出结果:
通用方法一
通用方法二
I believe i can fly
通用方法一
喜欢吃水果
通用方法二
**********体现动态性
通用方法一
Nike工厂生产一批衣服
通用方法二

动态代理与AOP

AOP:Aspect Orient Programming

AOP代理的方法:创建一个包含通用方法的类,将需要的通用方法加入invoke中即可。(现在还不会,等会了以后再回来补齐阿巴阿巴)。

总结:TMD好难(×)

动态代理相比静态代理,其运用了java中的反射机制,从而可以更加的灵活。
两者的创建过程基本相同,即:
1.需要有共同实现的接口
2.需要创建被代理类

不同之处:
1.动态代理需要实现InvocationHandler接口。
2.动态代理的代理类需要使用Proxy类的方法灵活创建被代理类的对象

只是初学萌新的一些理解,希望大佬指正。

上一篇:c#-通过字符串从局部变量获取属性


下一篇:PHP常用魔术方法(__invoke魔术方法)