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。总结

        代码的灵活,就像生活一般。在代码灵活的过程中。我们就会对照下生活,生活中。我们每一个人,事。物都是独立的对象。而在生活中的时间轴中。我们也是过程化的组织,我们的代码和生活。在思想上都是同样的。优化的不不过代码,还有思想啊。
    
  • 相关阅读:
    Elementary Methods in Number Theory Exercise 1.2.25
    Elementary Methods in Number Theory Exercise 1.2.14
    图解欧几里德算法
    图解欧几里德算法
    Elementary Methods in Number Theory Exercise 1.2.14
    Android中的长度单位详解(dp、sp、px、in、pt、mm)
    分享下多年积累的对JAVA程序员成长之路的总结
    android异常之都是deamon惹的祸The connection to adb is down, and a severe error has occured.
    TomatoCartv1.1.8.2部署时报错
    JavaScript浏览器对象之二Document对象
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7141910.html
Copyright © 2011-2022 走看看