上篇讲述了Spring的IOC原理和使用,本篇讲述Spring对AOP的支持。首先回顾一下Spring IOC容器,用一种通俗的方式理解Spring的IOC,也就是家里要安装灯泡,去网上买,我们只需要去下订单就(ApplicationContext.xml)可以了,无需关心工厂是如何加工的,你想要灯泡发红的光就直接在选择的时候选择红光,如果想要发黄色光的就直接选择发黄色光的灯牌,之后生成订单后会有派件人员直接派送到你的家门口,不需要你自己创建灯泡工厂去生产(new)灯泡。
那什么是Spring的AOP呢?
我们可以理解为你想要给灯安装一个灯罩,可以直接把灯罩起来,而这个灯罩相对于灯本身来说没有任何的关系,是独立存在的,你只要加上去就可以。对于这个灯罩来说,就是从AOP的角度去分析了。
那究竟什么是Spring的IOC容器呢?
在软件业,AOP是AspectOriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。也可以意为面向行为编程,是函数式编程的一种衍生范型。
我们以一个例子来说明什么是AOP。
例如我们在用户增删改查上添加一个安全性检查,这样无论是任何操作之前都要进行安全性检查。
UserManager.java接口代码如下所示。
public interface UserManager {
public void addUser(String name,String password);
public void delUser(int userId);
public String findUserById(int userId);
public void modifyUser(int userId,String username,String password);
}
UserManagerImpl.java实现接口代码如下所示。
public class UserManagerImpl implements UserManager {
@Override
public void addUser(String name, String password) {
checkSecurity();
System.out.println("------------UserManagerImpl.add()----");
}
@Override
public void delUser(int userId) {
checkSecurity();
System.out.println("------------UserManagerImpl.del()----");
}
@Override
public String findUserById(int userId) {
checkSecurity();
System.out.println("------------UserManagerImpl.findUserById()----");
return "张三";
}
@Override
public void modifyUser(int userId, String username, String password) {
checkSecurity();
System.out.println("------------UserManagerImpl.ModifyUser()----");
}
//检查安全性.
//当安全性不需要时就要成百上千给去改动,
//我们就可以用代理模式,让代理去做,让代理去控制目标,代理做某件事情.
private void checkSecurity()
{
System.out.println("------------UserManagerImpl.checkSecurity()----");
}
}
这样的话如果我们想要更改的话就要在这个类上对安全性检查进行更改,添加的话也需要修改这个类的代码进行添加,这不符合我们设计原则,开闭原则,对扩展开放,对修改关闭。那怎么办呢?我们从中可以发现,检查安全性来说对增删改查的操作没有影响,是一项独立存在的方法或独立存在的服务,这样我们可以把检查安全性这以服务抽取出来放到UserManagerImpl类的代理类中,这样去分开这个独立的服务。让代理去实现相同的接口,调用UserManagerImpl中的方法,把服务单独的放到代理类中。这样单独的管理这项服务。
使用静态代理解决问题
代理类代码如下所示。UserManagerImplProxy.java,加上代理类之后我们就可以去掉UsermanagerImpl.java中的安全性检查方法。
/**
* 代理类和目标做的事情是一样的,所以实现相同的接口.
* @author Summer
*
*/
public class UserManagerImplProxy implements UserManager {
//目标引用.
private UserManager userManager;
//通过构造方法传递过来.
public UserManagerImplProxy(UserManager userManager)
{
this.userManager = userManager;
}
@Override
public void addUser(String username, String password) {
checkSecurity();
userManager.addUser(username, password);
}
@Override
public void delUser(int userId) {
// TODO Auto-generated method stub
checkSecurity();
userManager.delUser(userId);
}
@Override
public String findUserById(int userId) {
checkSecurity();
return userManager.findUserById(userId);
}
@Override
public void modifyUser(int userId, String username, String password) {
checkSecurity();
userManager.modifyUser(userId, username, password);
}
private void checkSecurity()
{
System.out.println("------------UserManagerImpl.checkSecurity()----");
}
}
但问题是要去修改的这个安全性检查的方法的话,就要去修改代理类了,如果很多方法,就要修改很多次,会引来同样的开闭问题。
我们应该剥离出来,让这个方法在运行的时候动态的加入进去,方法只写一次,从AOP