Spring2.0技术手册笔记——AOP_1_AOP概念与简单实现

   Ioc之前看了一些书籍,有写概念,而AOP则基本没什么概念。感觉比较深奥,就先从这里开刀。不过看了看,感觉其实就那么回事。
    一般情况下,一个方法里面除了完成业务外,肯定会加入一些其他多余的东西。。。。log(这个东西可能国外用得比较多,国内可能有这个习惯的人不多,我新手,肯定没这个习惯了。。。。),安全检查(这个应该是到处可见)。这样的话,这个方法就不‘纯’了。如果哪天你要把这写多余的东西去掉,那就要一个方法一个方法的去找。会累死人的。AOP就为解决这个问题的。
    先看代码(代码都为技术手册实例,简单明了!)。
    最原始也是最快速的给方法添加log的方法就像这样写。
import java.util.logging.Level;
import java.util.logging.Logger;

/*A normal java Class which will be 
compared with a Class using AOP*/

public class NormalClass {
	private Logger log = Logger.getLogger(this.getClass().getName());
	
	public void hello(String name){
		//log before print
		log.log(Level.INFO,"hello method starts....");
		//print
		System.out.println("Hello," + name);
		//log after print
		log.log(Level.INFO,"hello method ends....");
	}
}

    假如100个方法都要加log,重复代码可想而知了。(英文注释自己写的,书写水平很烂,阅读水平一般,欢迎拍砖。。。。)
   下面是以静态代理来实现最简单的aop。首先,定义个接口。实现类和代理类都实现此接口。
public interface SayHello {
	void hello(String hello);
}

    然后是实现类,里面就是最简单的业务处理---打印。
import staticproxy.inter.SayHello;

public class SayHelloImpl implements SayHello{

	@Override
	public void hello(String name) {
		System.out.println("Hello," + name);
	}
	
}

     接着是代理类,代理类里添加log。
import java.util.logging.Level;
import java.util.logging.Logger;

import staticproxy.inter.SayHello;

public class SayHelloImplProxy implements SayHello {
	
	private SayHello say;
	private Logger log ;
	
	public SayHelloImplProxy(SayHello say){
		this.say = say;
		log = Logger.getLogger(this.say.getClass().getName());
	}

	@Override
	public void hello(String name) {
		log.log(Level.INFO,"hello method starts....");
		this.say.hello(name);
		log.log(Level.INFO,"hello method ends....");
	}

}

    测试一下。
import dynamicproxy.LogHandler;

import staticproxy.SayHelloImpl;
import staticproxy.SayHelloImplProxy;
import staticproxy.inter.SayHello;
import normal.NormalClass;


public class Test {
	public static void main(String[] args){
		//Test normal.NormalClass
		NormalClass nor = new NormalClass();
		nor.hello("Ivan");
		
		//Test staticproxy.SayHelloImpl
		SayHello say = new SayHelloImplProxy(new SayHelloImpl()); 
		say.hello("Ivan");
		
			}
}

    两个输出应该是一样的。这样就把业务和log分开了。这是代理模式的简单体现,应该很简单。不过缺点显而易见,每个类都得有个代理类。
    于是就有了动态代理。直接实现java.lang.reflect.InvocationHandler接口即可。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.logging.Level;
import java.util.logging.Logger;

public class LogHandler implements InvocationHandler {

	private Logger log = Logger.getLogger(this.getClass().getName());
	private Object delegate;

	public Object bind(Object delegate) {
		this.delegate = delegate;
		return Proxy.newProxyInstance(delegate.getClass().getClassLoader(),
				delegate.getClass().getInterfaces(), this);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object res = null;
		
		log(method + " method starts....");
		res = method.invoke(delegate, args);
		log.log(Level.INFO,method + " method ends....");		
		
		return res;
	}

	private void log(String message) {
		log.log(Level.INFO,message);
	}

}

    看起来好像挺复杂,其实和静态代理一样。其中的bind就相当于静态代理的构造方法。然后在调用时,会自动的调用invoke方法,在invoke方法里添加了log。
    其他代码和静态代理的一模一样。不重复。
    这样的话,你想在哪个方法里添加log,只要bind那个类就可以了。
    这就是AOP了,没什么深奥的。就实现方法有区别而已。Spring里的AOP就是用动态代理实现的。

    下面通过上面的代码解释几个AOP的名词。
    1.Cross-cutting concern(直译应该叫“横切关注点”)
      我理解的就是,需要以AOP来处理的东东。像log,安全检查这些。
    2.Aspect(方面)
     就是对于那些横切关注点所编写的类。如LogHandler。
    3.Advice(原意“忠告”,感觉莫名其妙。)
     可以理解为,在Aspect里面,实现的Cross-cutting concern的具体方法.如Loghandler里的invoke方法。
    4.Joinpoint
      Advice被执行的那个时机。(感觉比较抽象。保留意见。)
    5.Pointcut
      可以理解为Joinpoint执行的条件,符合Pointcut的Joinpoint才执行。
    6.Target
      简单理解为被代理的那个对象。如SayHelloImpl。
    7.Introduction
      给一个已编写或编译玩的类,在执行期间动态地加入一些方法或行为,而不修改或新增任何一行程序代码。(不解其意。。。。不是不懂他说的意思,而是不解,他说的是Introduction这个东东的功能还是什么。)
     8.Proxy(代理)
       。。。。
     9.Weave(编织,组合,编排)
      Advice被应用至对象之上的过程称之为Weave。
     

你可能感兴趣的:(java,spring,AOP,IOC)