zoukankan      html  css  js  c++  java
  • 谈谈什么是AOP以及动态代理技术

    摘要

    本文讲解了aop的基本概念,并且简要的介绍了其实现原理。

    AOPのwhy以及what

    我们都知道,软件的良好组织应该是分模块的,而且这种模块最好是垂直结构的。OOP思想正好契合这种设计模式。但是在我们的实际软件组织中,有些功能总是会破坏这种结构,设想下面的场景,在程序设计中,我们最常用的功能便是日志功能了,我们无法把这些日志代码集中管理起来,他总是会散布在我们的代码中,将我们的代码污染。又或者我们需要在现有业务逻辑上加入一些特定的功能,这些功能也许或许每个模块都需要,比如说我们需要监测每个模块的性能,又或者为每个模块添加一些安全检查逻辑,但是又不能为使用该模块的使用者带来麻烦,也就是说我们想用非侵入式编程的方法实现此功能。在面向对象中,我们只能采用继承式的方法来添加这些逻辑。但是这样最明显的问题及时,代码组织会迅速膨胀。加入说我们原先有100个具体的类,我们想为每个类添加打印日志功能,这样我们就需要继承这100个类,重写每一个需要打印日志的方法。久而久之,我们的软件一定会变得难以管理。AOP就是为了解决这个问题而提出的。它采用了动态代理的思想,实现了上述的功能。

    动态代理

    为方便讲述动态代理,用下面的具体例子来帮助理解,假设我们软件模块中有这样的一个类SomeTask,我们现在想为这个类添加一些额外的功能。比如我现在想进行一些安全检查的代码。我们应该怎么办?(我,还能怎么办,打开SomeTask的代码,进入到具体方法,改就完事了。AOP:滚!)下面用伪代码进行描述:

    interface Task{
        public void execute(args:Object[]);
    }
    Class SomeTask implements Task {
        public void execute(args:Object[]) {
            
        }
    }
    interface SecurityCheck{
        public boolean securityCheck();
    }
    class SecurityCheckImpl implements SecurityChcek{
        public boolean securityCheck(){
            
        }
    }
    

    假如我们不允许对SomeTask的源代码进行改动,我们能想到最直接的方法便是面向白盒编程,也及时继承Task,然后进行方法的重写。代码如下:

    class TaskWithSecurityCheck implements Task{
        private Task task;
        private SecurityCheck sc;
        public TaskWithSecurityCheck(Task t,SecurityCheck s){
            task = t;
            sc = s;
        }
        @Override
        public void execute(args:Object[]) {
            boolean success = sc.securityCheck();
            if(success) task.execute();
            else {
                System.out.prrintln("securiy check fail forbbiden execute the task");
            }
        }
    }
    

    嗯,这样的代码也还可以,当我们的软件规模不大时,但是设想一下,假如我们需要为每个模块假如这样的安全检查呢,头铁的可以继续刚,我还是去寻找更好的解决方案了。这个时候,实际上需要我们的动态代理出场了,哦,对了,上面的模式叫做静态代理模式。

    动态代理可以实现将欲添加的功能完全抽象出来,那个模块想要添加这个功能,动态的添加就好了,非常的方便。话不多说,我们直接看代码:

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class SecurityCheckProxy implements InvocationHandler {
    	private Object target;
        private SecurityChcke sc;
    	public CalTaskTimeProxy(Object t,SecurityCheck sc) {
    		this.target = t;
            this.sc = sc;
    	}
    	@SuppressWarnings("unchecked")
    	public  <T> T create() {
    		return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    	}
    	@Override
    	public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
    		//before();
    		Object result = null;
                   boolean success = sc.securityCheck();
    		try {
                        if(success) result = method.invoke(target,args);
                        return result;
    		} catch (IllegalAccessException e) {
    		}
                    finally{
                        if(result == null) {
                        System.out.println("task forbbiden execute cause security check fail");
                 }
             }
    	}
    }
    

    我们的客户端调用代码如下:

    public void main(String[] args) {
        Task task = new SecurityCheckProxy(new SomeTask();
            			new SecurityCheckImpl()).create();
        task.execute();
    }
    

    可以看出,在客户端的使用除了多了需要配置的代理以外,没有任何的异常,这样我们就实现了对于原先代码不进行任何改动的前提下,从而添加了我们想要的新功能。实际上这也是AOP实现的基本思想。同时也是java反射的一个经典应用。

  • 相关阅读:
    ZOJ Problem Set–2417 Lowest Bit
    ZOJ Problem Set–1402 Magnificent Meatballs
    ZOJ Problem Set–1292 Integer Inquiry
    ZOJ Problem Set–1109 Language of FatMouse
    ZOJ Problem Set–1295 Reverse Text
    ZOJ Problem Set–1712 Skew Binary
    ZOJ Problem Set–1151 Word Reversal
    ZOJ Problem Set–1494 Climbing Worm
    ZOJ Problem Set–1251 Box of Bricks
    ZOJ Problem Set–1205 Martian Addition
  • 原文地址:https://www.cnblogs.com/zhangshoulei/p/13280793.html
Copyright © 2011-2022 走看看