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

    代码的灵活,就像生活一般。在代码灵活的过程中。我们就会对照下生活,生活中。我们每一个人,事。物都是独立的对象。而在生活中的时间轴中。我们也是过程化的组织,我们的代码和生活。在思想上都是同样的。优化的不不过代码,还有思想啊。

posted on 2017-07-09 16:35  yjbjingcha  阅读(200)  评论(0编辑  收藏  举报

导航