您的位置:首页 > 编程语言

Aop_面向切面编程(1)_思想理解

2012-06-28 15:14 615 查看
Aop的基本思想

开发人员在编写应用程序时,通常包含两种代码:一种是和业务系统有关系的代码,一种是和业务系统关系不大的代码,例如日志,事务处理,权限处理等等。以前的程序中,这两种代码是写在一起的。这样一来,程序中到处充满着相同或类似的代码,不利于维护。而Aop的目标就是使这两种代码分离解耦,这样程序员就能专心于业务的处理,而且达到维护和重用的目的。

拿日志记录这个例子来看。每个方法都需要进行日志记录,不使用Aop的时候,每个方法中都要包含日志记录的代码,这样就会产生重复,而且日志记录和业务代码紧紧耦合,不利于维护。使用AOP的思想,可以把日志看成是一个切面,所有需要日志记录的方法都要经过这个切面。这样就可以把日志记录的代码封装,当方法经过切面的时候执行,这样就实现了代码重用。

Aop和oop的关系

一个程序分为核心关注点和横切关注点,oop关注核心,aop关注横切。在aop中每个关注点并不知道是否有其他关注点关注它,这是oop和aop的区别。Oop和aop是互补的思想,而不是对立。

Aop和java的代理机制

Aop是一种思想,他和具体的实现技术无关。任何符合aop思想的技术实现都可以看做是Aop的实现。

Jdk 1.3之后java提供动态代理机制。通过java的动态代理可以轻松实现Aop。事实上spring的Aop也是建立在java的动态代理机制之上的。要理解spring,就要先理解java的动态代理机制。

通过日志记录的实例分析AOP思想

(Log4j下载地址列表:http://www.apache.org/dyn/closer.cgi/logging/log4j/1.2.17/log4j-1.2.17.zip

//关于log4j的使用请参看本博客另一篇文章《log4j使用快速入门 》,配置文件和log4j.jar在本例源码中有。

日志记录的三种实现:

1.不使用aop思想的实现

/**

* 客户端程序

* @author yanwushu

*

*/

public class Browser {

public static void main(String[] args) {

new Register().register("张三");

}

}

/**

*

* 注册机类

* @author yanwushu

*

*/

public class Register {

//一个日志记录器成员

Logger logger = Logger.getLogger(this.getClass().getName());

/**

* 注册方法

*/

public void register(String name ){

logger.info(name+"开始审核");

System.out.println("正在注册...");

logger.info(name+"注册完毕");

}

}

这样的方式,每个需要日志记录服务的方法都必须重复logger.info()这样的代码,且这些和业务逻辑无关的代码和业务逻辑紧紧耦合不利于维护,让程序员不能集中精力在业务的处理上。

2.使用静态代理模式实现Aop来实现日志服务

/**

* 客户端

* @author yanwushu

*

*/

public class Browser {

//使用静态代理模式实现Aop

public static void main(String[] args) {

Register register = new RegisterImpl();

RegisterProxy proxy = new RegisterProxy(register);

proxy.register("张三");

}

}

/**

* 注册机接口

* @author yanwushu

*

*/

public interface Register {

//定义注册服务

public void register(String name);

}

/**

* 注册机实现类

* @author yanwushu

*

*/

public class RegisterImpl implements Register {

@Override

public void register(String name) {

System.out.println(name+"正在注册");

}

}

/**

* 注册代理类

*/

public class RegisterProxy {

//一个日志记录器成员

Logger logger = Logger.getLogger(this.getClass().getName());

//一个注册接口的引用

private Register register;

public RegisterProxy(Register register){

this.register = register;

}

public void register(String name){

logger.debug("正在审核....");

register.register(name);

logger.debug("注册完毕");

}

}

这种实现的好处是把业务代码和与业务无关的记录日志的代码解耦。这样有利于代码的维护和程序员精力集中在业务的处理上。这样就已经实现了Aop的思想。在这里面向的切面就是日志记录这个横切关注点。不过使用静态代理的方式由一个坏处(也是静态代理模式的短板)就是当被代理类数量扩展的时候不得不扩展响应的代理类,进而造成代理类泛滥。

3.使用jdk 1.3之后的动态代理机制来实现Aop

/**

* 客户端代码

* @author yanwushu

*

*/

public class Browse {

public static void main(String[] args) {

//实例化日志代理类

LogProxy logProxy = new LogProxy(new RegisterImpl());

//动态获取代理实例

//参数:注册类的类装载器,被代理的接口,日志代理的实例

Register re = (Register)Proxy.newProxyInstance(RegisterImpl.class.getClassLoader(), RegisterImpl.class.getInterfaces(),logProxy);

re.register("张三");

}

}

/**

* 日志代理类,他可以代理一切需要日志输出服务的类

* 它实现了调用处理者接口

* @author yanwushu

*

*/

public class LogProxy implements InvocationHandler{

//一个日志记录器成员

private Logger logger = Logger.getLogger(this.getClass().getName());

//被代理者成员

private Object beProxy;

public LogProxy(Object beProxy){

this.beProxy = beProxy;

}

//实现调用方法

@Override

public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

Object result ;

logger.debug("正在审核");

result = method.invoke(beProxy, args);

logger.debug("注册完毕");

return result;

}

}

/**

* 注册机接口

* @author yanwushu

*

*/

public interface Register {

//定义注册服务

public void register(String name);

}

/**

* 注册机实现类

* @author yanwushu

*

*/

public class RegisterImpl implements Register {

@Override

public void register(String name) {

System.out.println(name+"正在注册");

}

}

Java 1.3之后的动态代理机制(参看java.lang.reflect.Proxy,java.lang.reflect.InvocationHandler)可以动态生成代理类(内部使用java的反射机制,参看java.lang.reflect包)。这样就弥补了静态代理的先天不足。不用担心代理类泛滥了。

点击下载本例代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: