• 动态代理模拟简单的AOP


    参照MOOC<java核心技术高阶>,使用java动态代理来实现一个简单的AOP

    AOP vs. OOP

    OOP

    面向对象编程,将功能需求划分为独立的、不同的、功能完善的类,通过继承、多态等方式实现相同或者不同的行为

    AOP

    面向切面编程,将通用的需求功能从众多类中提取出来,使得众多类共享一个行为。

    关系

    AOP是OOP的补充
    OOP的不足之一关键业务和非关键业务的耦合。
    如雇员类Employee,核心业务是work,非核心的业务(高可变性)是记录(record) work前
    后的状态信息,比如开始时间、使用的工具等,随着需求可能不断变化。
    如果只使用OOP,那么要把非关键业务代码record写入类中,一方面是耦合性高,另一方面是这种
    高可变性的业务可能造成修改频繁,难以维护。
    如何将非关键业务从耦合中分离出来,统一管理,便于修改? --AOP

    怎么实现AOP?
    java动态代理的特性很适合AOP。
    动态代理会拦截特定的方法调用,进行加工(添加非关键的业务),在调用真正的业务方法。

    利用动态代理实现一个SimpleAOP

    场景描述:

    有Person类,关键业务是eat,非关键业务是在eat之前洗手(wash hands),
    eat之后擦嘴(wipe mouth)

    具体步骤:
    1- 创建Person接口

    public interface Person {
        void eat();
        String getName();
    }
    

    2- 实现Person

    public class PersonImpl implements Person {
        private String name;
        public PersonImpl(String name){
            this.name =name;
        }
        @Override
        public void eat(){
            System.out.println(name+" is eating!");
        }
    
        @Override
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

    3- 创建调用处理器(实现InvocationHandler)

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    public class PersonProxyHandler implements InvocationHandler {
        private Person person;//持有真正被调用的对象
        public PersonProxyHandler(Person p){
            this.person=p;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
            //before eat
            System.out.println(person.getName()+" is washing hands!");
            //eat
            Object res = method.invoke(person,args);
            //after eat
            System.out.println(person.getName()+" is wiping mouth!");
            return res;
        }
    }
    

    4- 生成动态代理并调用方法

    import java.lang.reflect.Proxy;
    public class Main {
        public static void main(String[] args) {
            //创建目标对象
            PersonImpl edwinxu = new PersonImpl("Edwin0");
            //创建调用处理器对象
            PersonProxyHandler pph = new PersonProxyHandler(edwinxu);
            //动态生成代理对象
            Person personProxy = (Person) Proxy.newProxyInstance(
                    PersonImpl.class.getClassLoader(),PersonImpl.class.getInterfaces(),pph
            );
            while (true){
                try {
                    personProxy.eat();//执行关键业务代码
                    edwinxu.setName("Edwin"+(int)(Math.random()*10));
                    Thread.sleep(3000);
                    System.out.println();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
    

    特殊说明:

    要模仿AOP,按道理理应使用配置文件形式,但是这里简化了。

    输出:

    Edwin0 is washing hands!
    Edwin0 is eating!
    Edwin0 is wiping mouth!
    
    Edwin5 is washing hands!
    Edwin5 is eating!
    Edwin5 is wiping mouth!
    

    可见通过动态代理,在关键业务(eat)上添加了一些其他的高可变的非关键业务。

  • 相关阅读:
    HDU 1402 A * B Problem Plus (FFT)
    CodeForces 935E Fafa and Ancient Mathematics (树形DP)
    HDU 5355 Cake (构造 + 暴力)
    HDU 5360 Hiking (贪心)
    Java高阶回调,回调函数的另一种玩法
    关于git 指令
    Retrofit2 完全解析 探索与okhttp之间的关系
    HTTP中GET与POST的区别
    TCP,IP,HTTP,SOCKET区别和联系
    android 实现类似qq未读消息点击循环显示
  • 原文地址:https://www.cnblogs.com/XT-xutao/p/12804087.html
Copyright © 2020-2023  润新知