码迷,mamicode.com
首页 > 编程语言 > 详细

java架构解密——实时动态aop

时间:2015-06-30 01:27:47      阅读:201      评论:0      收藏:0      [点我收藏+]

标签:

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

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 客户端

/**
 * 执行代理程序的客户端
 *
 * @author 许恕
 * @version 3.0.0 , 2015年6月16日 下午3:18:42
 */
public class 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,总结

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

java架构解密——实时动态aop

标签:

原文地址:http://blog.csdn.net/xvshu/article/details/46689237

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!