静态代理与动态代理以及AOP与动态代理

本文深入探讨了代理模式,包括静态代理和动态代理。静态代理通过创建代理类来控制对目标对象的访问,而动态代理则在运行时通过反射机制创建。动态代理进一步分为JDK动态代理和CGLIB动态代理,允许在运行时为任意对象创建代理,增加了代码的灵活性。代理模式在AOP(面向切面编程)中扮演重要角色,用于添加如日志、事务处理等横切关注点。
摘要由CSDN通过智能技术生成

代理Proxy:

Proxy代理模式是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。
更通俗的说,代理解决的问题当两个类需要通信时,引入第三方代理类,将两个类的关系解耦,让我们只了解代理类即可,而且代理的出现还可以让我们完成与另一个类之间的关系的统一管理,但是切记,代理类和委托类要实现相同的接口,因为代理真正调用的还是委托类的方法。

更通俗的说,代理解决的问题当两个类需要通信时,引入第三方代理类,将两个类的关系解耦,让我们只了解代理类即可,而且代理的出现还可以让我们完成与另一个类之间的关系的统一管理,但是切记,代理类和委托类要实现相同的接口,因为代理真正调用的还是委托类的方法。
  • 静态:由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。
  • 动态:在程序运行时运用反射机制动态创建而成。

静态代理:

/**
 * @Description  :  TODO
 * @author       :  hmwh
 * @Creation Date:  2020-06-06 13:44
 */
interface ClothFactor{
    void produceCloth();
}

//代理类
class ProxyClothFactory implements ClothFactor{

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

    public ProxyClothFactory(ClothFactor factor){
        this.factor=factor;
    }

    @Override
    public void produceCloth() {
        System.out.println("开始");
        factor.produceCloth();
        System.out.println("停止");
    }
}
//被代理类对象
class NikeClothFactory implements ClothFactor{

    @Override
    public void produceCloth() {
        System.out.println("Nike");
    }
}
public class StaticProxyTest {
    public static void main(String[] args) {
        //创建被代理类对象
        NikeClothFactory nike = new NikeClothFactory();
        //创建代理类对象
        ProxyClothFactory factory = new ProxyClothFactory(nike);
        factory.produceCloth();
    }
}

输出结果

开始
Nike
停止

动态代理:

/**
 * @Project Name :  untitled
 * @Package Name :  aop
 * @Description :  TODO
 * @author :  hmwh
 * @Creation Date:  2020-06-06 14:01
 * @ModificationHistory Who    When    What
 * --------  ---------  --------------------------
 */
package aop;

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

/**
 * @Description  :  TODO
 * @author       :  hmwh
 * @Creation Date:  2020-06-06 14:01
 */

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("I Like " + food);
    }
}

/*
    需要实现动态代理需要解决的问题
    1、如何根据加载到内存中的被代理类,动态创建一个代理类及其对象
    2、当通过代理类的对象调用方法a时,如何动态的去调用被代理类中的同名方法a
 */
class ProxyFactory{
    //调用此方法,返回一个代理类对象
    public static Object getProxyInstance(Object obj){  //obj:代理对象

        MyInvocationHandler invocationHandler = new MyInvocationHandler();
        invocationHandler.bind(obj);

        //获取类的加载器,类的继承接口
        Object instance = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),invocationHandler);
        return instance;
    }
}

class MyInvocationHandler implements InvocationHandler{
    private Object obj;

    public void bind(Object obj){
        this.obj = obj;
    }

    //当通过代理类的对象,调用方法a时,就会自动调用如下方法:invoke()
    //将被代理类需要执行的方法a的功能声明在invoke()中
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {

        //method:即为代理类对象调用方法,此方法也作为被代理类对象要调用的方法
        //obj:被代理类的对象
        Object invoke = method.invoke(obj, objects);
        //代理类对象调用的方法的返回值作为当前类中的invoke()的返回值
        return invoke;
    }
}

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

        System.out.println("------------------------");

        NikeClothFactory nikeClothFactory = new NikeClothFactory();

        ClothFactor proxyInstance1 = (ClothFactor) ProxyFactory.getProxyInstance(nikeClothFactory);

        proxyInstance1.produceCloth();
    }
}

输出结果

I believe I can fly!
I Like 汉堡
------------------------
Nike

AOP(AspectOrientedProgramming):

面向切面,将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码—解耦。
这里我们添加一个HumanUtil作为模拟这里我们添加一个HumanUtil作为模拟

/**
 * @Project Name :  untitled
 * @Package Name :  aop
 * @Description :  TODO
 * @author :  hmwh
 * @Creation Date:  2020-06-06 14:01
 * @ModificationHistory Who    When    What
 * --------  ---------  --------------------------
 */
package aop;

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

/**
 * @Description  :  TODO
 * @author       :  hmwh
 * @Creation Date:  2020-06-06 14:01
 */

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("I Like " + food);
    }
}
//----------
class HumanUtil{
    public void method1(){
        System.out.println("通用方法1---------------------");
    }
    public void method2(){
        System.out.println("通用方法2---------------------");
    }

}
//---------
/*
    需要实现动态代理需要解决的问题
    1、如何根据加载到内存中的被代理类,动态创建一个代理类及其对象
    2、当通过代理类的对象调用方法a时,如何动态的去调用被代理类中的同名方法a
 */
class ProxyFactory{
    //调用此方法,返回一个代理类对象
    public static Object getProxyInstance(Object obj){  //obj:代理对象

        MyInvocationHandler invocationHandler = new MyInvocationHandler();
        invocationHandler.bind(obj);

        //获取类的加载器,类的继承接口
        Object instance = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),invocationHandler);
        return instance;
    }
}

class MyInvocationHandler implements InvocationHandler{
    private Object obj;

    public void bind(Object obj){
        this.obj = obj;
    }

    //当通过代理类的对象,调用方法a时,就会自动调用如下方法:invoke()
    //将被代理类需要执行的方法a的功能声明在invoke()中
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {

        HumanUtil util = new HumanUtil();
        util.method1();
        //method:即为代理类对象调用方法,此方法也作为被代理类对象要调用的方法
        //obj:被代理类的对象
        Object invoke = method.invoke(obj, objects);


        util.method2();

        //代理类对象调用的方法的返回值作为当前类中的invoke()的返回值
        return invoke;
    }
}

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

        System.out.println("------------------------");

        NikeClothFactory nikeClothFactory = new NikeClothFactory();

        ClothFactor proxyInstance1 = (ClothFactor) ProxyFactory.getProxyInstance(nikeClothFactory);

        proxyInstance1.produceCloth();
    }
}

输出结果

通用方法1---------------------
通用方法2---------------------
I believe I can fly!
通用方法1---------------------
I Like 汉堡
通用方法2---------------------
------------------------
通用方法1---------------------
Nike
通用方法2---------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值