zoukankan      html  css  js  c++  java
  • java架构解密——实时动态aop

      在上篇博客中个。咱们一起组建了一个容器,里面封装了业务,这样,咱们就将业务和服务的组装放到了client,而client就相当于咱们的开发中使用到的配置文件。大家发现问题了吗?就是我不能动态修改了?业务容器在代理完毕后,又一次加入一个容器。这时候。是不被同意的,那这个容器就是个编译时起作用的容器,他就丧失了非常多的灵活性。
      那怎么办呢?实际就是调换一下调用顺序就好。大家看看结果:
    

    1,类图对照

    旧版的系统

      改造后类图
    

    改造后的图

    2,代码实现:

    2.1代理类的变化:

    
    /**
     * 打招呼动态代理类,给业务类加入功能
     * 前一版本号为JDK代理实现
     *  本次加入运行方法之前打印到控制台‘befor’
     *  本次加入运行方法之后打印到控制台‘after’
     *本次版本号为DGLIB代理
     *  换代理类原因,JDK代理要求被代理类必须实现某接口,由于它底层实现是新建一个类,实现和被代理类同样的接口
     *  用代理类新建的业务类代替原业务类
     *  CGLIB代理是新建一个类。继承自被代理类,用新建的代理类替换掉原业务类,就不须要接口了
     *
     *5.0版本号添加服务组装容器,将服务从代理类中抽离出去了,我们的代理类成为了一个bean
     *6.0将服务容器定义为接口
     *7.0添加业务容器
     *8.0 业务容器不灵活,将获代替理放置到业务容器端,实现动态添加元素,也能拿到代理
     * @author 许恕
     * @version 3.0.0 , 2015年6月16日 下午3:20:13
     */
    public class CGLibDynamicProxy implements MethodInterceptor {  
    
        //服务类容器
        private IProxyMehds proxyMehds;
    
      //代理工厂类:单例模式,优化内存开销
        private static CGLibDynamicProxy instance = new CGLibDynamicProxy();  
    
        //构造函数
        private CGLibDynamicProxy() {  
        }  
    
        //获取cglib代理工厂类
        public static CGLibDynamicProxy getInstance() {  
            return instance;  
        }  
    
        /**
         * 使用代理工厂生成某个类的代理
         *
         * @param cls 要代理的类
         * @return 返回已经代理好的类
         */
        @SuppressWarnings("unchecked")  
        public <T> T getProxy(Class<T> cls) {  
            return (T) Enhancer.create(cls, this);  
        }  
    
    
        //重写被代理对象的方法运行
        //全部的方法运行。到反射的级别都是invoke,重写了这种方法,就重写了全部的方法运行,实现了代理
        @Override 
        public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {  
            //重要改进:从服务容器中运行方法,不再是写死的!
            proxyMehds.beforeBean(); 
    
            //方法正常运行的语句
            Object result = proxy.invokeSuper(target, args);
    
            //重要改进:从服务容器中运行方法。不再是写死的!
            proxyMehds.afterBean(); 
    
    
            return result;   
        }
    
        //服务容器的get方法
        public IProxyMehds getProxyMehds() {
            return proxyMehds;
        }
    
        //服务容器的set方法
        public void setProxyMehds(IProxyMehds proxyMehds) {
            this.proxyMehds = proxyMehds;
        }
    
    
    
    }

    2.2业务容器

    /**
     * 业务类容器:
     *  用map盛放要切入服务的业务类
     *
     * @author 许恕
     * @version 3.0.0 , 2015-6-29 14:25:21
     */
    public class DoMehds  implements IDoMehds {
        //盛放运行业务的map
        private  HashMap<String,Object> DoBeans;
    
        //代理类
        private CGLibDynamicProxy proxy ;
    
        /**
         * 封装获取元素的方法。每次获取元素都封装一个代理
         *
         * @param 元素的名字
         * @return 代理好的元素
         */
        public Object getBean(String beanName){
            return proxy.getProxy(DoBeans.get(beanName).getClass());
        }
    
        //获取业务map
        public HashMap<String, Object> getDoBeans() {
            return DoBeans;
        }
    
        //设置业务map
        public void setDoBeans(HashMap<String, Object> doBeans) {
            DoBeans = doBeans;
        }
    
        //获代替理类
        public CGLibDynamicProxy getProxy() {
            return proxy;
        }
    
        //设置代理类
        public void setProxy(CGLibDynamicProxy proxy) {
            this.proxy = proxy;
        }
    
    
    
    }

    2.3 client

    /**
     * 运行代理程序的client
     *
     * @author 许恕
     * @version 3.0.0 , 2015年6月16日 下午3:18:42
     */
    public class Client {
    
        //client运行的主方法:系统规定
        public static void main(String[] args) { 
            //盛放方法运行前的对象的容器
            HashMap<String,Object> beforBeans;
            HashMap<String,Object> afterBeans;
    
            //配制方法运行前要运行哪些方法
            HashMap<String,String> beforMethods;
            HashMap<String,String> afterMethods;
    
            //实例以上定义的服务类map
            beforMethods=new HashMap();
            beforBeans=new HashMap();
            afterMethods=new HashMap();
            afterBeans=new HashMap();
    
            //将服务类AspectClass1加入到方法运行要载入的服务类
            beforBeans.put("AspectClass1", new AspectClass1());
            beforBeans.put("AspectClass2", new AspectClass2());
            afterBeans.put("AspectClass3", new AspectClass3());
            afterBeans.put("AspectClass4", new AspectClass4());
    
            //规定每一个服务类要运行的方法
            beforMethods.put("AspectClass1", "SayHello");
            beforMethods.put("AspectClass2", "SayGoodBye");
            afterMethods.put("AspectClass3", "SayHi");
            afterMethods.put("AspectClass4", "Eat");
    
            //实例服务类容器。将四个map传入容器中
            ProxyMehds proxyMehds =new ProxyMehds();
            proxyMehds.setBeforBeans(beforBeans);
            proxyMehds.setBeforMethods(beforMethods);
            proxyMehds.setAfterBeans(afterBeans);
            proxyMehds.setAfterMethods(afterMethods);
    
            //实例业务map
            HashMap<String,Object> DoBeansMap = new HashMap<String,Object> ();
            //将业务装载到map中
            DoBeansMap.put("dobeans1", new GreetingImpl());
            DoBeansMap.put("dobeans2", new EatClass());
    
            //将业务map装载到容器中
            DoMehds doMehds = new DoMehds();
            doMehds.setDoBeans(DoBeansMap);
    
    
    
            //实例代理类
            CGLibDynamicProxy cglib =CGLibDynamicProxy.getInstance();
    
            //接受切面
            cglib.setProxyMehds(proxyMehds);
            doMehds.setProxy(cglib);
    
            //接受要代理的对象
            Greeting greeting = (Greeting)doMehds.getBean("dobeans1");
            EatClass eatObject = (EatClass)doMehds.getBean("dobeans2");
    
            //运行对象的某个方法
            greeting.sayHello("Jack");  
            eatObject.Eat();
        } 
    
    
    }

    3。总结

        代码的灵活,就像生活一般。在代码灵活的过程中。我们就会对照下生活,生活中。我们每一个人,事。物都是独立的对象。而在生活中的时间轴中。我们也是过程化的组织,我们的代码和生活。在思想上都是同样的。优化的不不过代码,还有思想啊。
    
  • 相关阅读:
    SQLServer 系统表简介
    C# abstract 和 virtual 关键字
    Windows脚本 %~dp0的含义
    Windows脚本 批处理中能够使用的系统变量
    Windows脚本 Shift 命令
    Windows脚本 关于本机ARP静态绑定批处理文件讲解[绑定ipmac脚本详解]
    开学测试
    仓库管理系统
    读《人月神话》
    个人作业2
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7141910.html
Copyright © 2011-2022 走看看