【回顾】
在之前的学习中,我们对Spring框架有了一个宏观认识,并且深入分析学习了它的核心内容IOC。从这篇博客,将开始对其另一个重要思想的实现展开学习,那就是AOP。
【前言】
AOP的意思是面向切面编程,英文全称是Aspect Oriented Programming,它是开发人员可以更好地将本不应该耦合在一起的功能分离开。
【内容】
一.认识AOP
开发人员在编写应用程序时,通常包含两种代码:一种是与业务逻辑相关的代码,一种是与业务逻辑关系不大的代码,例如日志、权限、事务处理、安全认证等。
以前编写代码,这两种代码都是写在一起的,这样在程序中,到处充满着相同或相似的代码,例如日志信息的输出,每个地方都要写日志方法的调用,这样就不利于程序的维护。而AOP就是这两种代码分离。使用AOP,就不用在业务逻辑代码中去实现与业务功能相关不大的代码,从而降低了两种代码的耦合性,达到易于维护和重用的目的。
AOP思想,以记录日志来说,每个方法都会调用到此方法,这样必然会有大量的重复性的代码。所以,我们可以将记录日志看作是一个横切面,所有对这些方法的调用都要经过这样的横切面,然后在横切面中进行记录日志的操作,便达到了对代码的重用和易于维护的目的。
二.OOP与AOP
OOP(面向对象编程),将现实问题领域的实体转换为软件系统中的对象,封装、继承和多态三大特性,对面向过程编程做了很大的改进。但OOP并不是一种完美的思想,在某些方面,还是存在缺点的。比如:日志管理、事务管理等,当应用OOP将这些内容封装为对象的行为时,会产生大量的重复的代码,虽然通过一些方法能够减少一些重复的问题,但并不能彻底解决问题。所以AOP就出现了。
AOP与OOP并不是两种对立的技术,人们不是为了要替代OOP而提出了AOP,而事实上,AOP与OOP可以很好地共存,AOP是OOP的有益补充,并不是对立面。
一个应用程序,可以分为核心关注点和横切关注点。核心关注点与具体功能有关,而横切关注点存在于整个应用系统中。在AOP中,每个关注点的实现并不知道是否有其他关注点关注它,这是AOP和OOP的主要区别。
三.AOP与Java代理机制
AOP是一种思想,并不是技术实现。任何一种符合AOP思想的实现,都可以看作是AOP的实现。
JDK1.3之后,Java提供了动态代理机制。通过动态代理,就很容易实现AOP的思想。实际上Spring的AOP也是建立在Java的代理机制上的,要理解AOP,就需要先理解Java的代理机制。
四.Java代理机制(安全验证实例)
如果不用代理机制,通常的情况下,程序中每个需要安全验证的代码都需要加上相同的代码,这样就会造成大量的重复。代码如下:
package com.bjpowernode.spring;
public class UserManagerImpl implements UserManager {
public void addUser(String username, String password) {
checkSecurity();
System.out.println("---------UserManagerImpl.add()--------");
}
public void delUser(int userId) {
checkSecurity();
System.out.println("---------UserManagerImpl.delUser()--------");
}
public String findUserById(int userId) {
checkSecurity();
System.out.println("---------UserManagerImpl.findUserById()--------");
return "张三";
}
public void modifyUser(int userId, String username, String password) {
checkSecurity();
System.out.println("---------UserManagerImpl.modifyUser()--------");
}
private void checkSecurity() {
System.out.println("-------checkSecurity-------");
}
下面就看看Java代理机制为我们做出了怎样的改变:
Java的InvocationHandler接口可以实现此功能,所以先创建一个安全验证的代理类,这个代理类实现了InvocationHandler接口:
package com.bjpowernode.spring;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class SecurityHandler implements InvocationHandler {
private Object targetObject;
public Object createProxyInstance(Object targetObject) {
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
checkSecurity();
//调用目标方法
Object ret = method.invoke(targetObject, args);
return ret;
}
private void checkSecurity() {
System.out.println("-------checkSecurity-------");
}
}
面向接口编程,在用户管理的实现层写出方法的具体实现:
package com.bjpowernode.spring;
public class UserManagerImpl implements UserManager {
public void addUser(String username, String password) {
System.out.println("---------UserManagerImpl.add()--------");
}
public void delUser(int userId) {
System.out.println("---------UserManagerImpl.delUser()--------");
}
public String findUserById(int userId) {
System.out.println("---------UserManagerImpl.findUserById()--------");
return "张三";
}
public void modifyUser(int userId, String username, String password) {
System.out.println("---------UserManagerImpl.modifyUser()--------");
}
使用安全认证代理类实现:
package com.bjpowernode.spring;
public class Client {
public static void main(String[] args) {
SecurityHandler hander = new SecurityHandler();
UserManager useraManager = (UserManager)hander.createProxyInstance(new UserManagerImpl());
useraManager.addUser("张三", "123");
}
}
这种方式也适用于其它类,真正地实现代码的重用,实现了业务逻辑代码和安全认证代码的分离。这就是Java动态代理的强大,而Spring的AOP正是建立在动态代理机制之上的。
【总结】
本篇博客让我们认识了AOP,利用Java的动态代理机制实现了AOP的思想,下一篇博客将开始AOP相关概念的学习,继续领略它的强大之处。