何为AOP ?
AOP(Aspect Oriented Programming)是Spring提供的关键特性之一。AOP即面向切面编程,是OOP编程的有效补充。
使用AOP技术,可以将一些系统性相关的编程工作,独立提取出来,独立实现,然后通过切面切入进系统。从而避免了在业务逻辑的代码中混入很多的系统相关的逻辑——比如权限管理,事物管理,日志记录等等。这些系统性的编程工作都可以独立编码实现,然后通过AOP技术切入进系统即可。从而达到了 将不同的关注点分离出来,可以单独维护大大降低了代码重复率以及不同层之间的耦合。
Struts2内部的AOP思想
举个例子,在Struts2中Params拦截器做的事情就是把前端请求过来的参数通过OGNL表达式对值栈里面的对象赋值,而这项操作正是对于每个Action执行前都要做的,因此选择了用拦截器将这部分代码分隔开来由Struts2自行完成不需要程序员干预。
Spring中对于事务的AOP处理
再如对于事务,我们在Service层要调用Dao层方法做增删查改需要开启事务/提交或回滚事务,这部分代码散落在每处的Service方法中,不宜与我们修改维护,不妨选择将他们独立封装起来,与其他业务分隔开。
AOP名词解释
Spring中实现AOP的方法(代理模式)
动态代理
被代理对象必须要实现父接口,才能产生代理对象.这种方式下我们生成的代理对象和被代理对象是同一个父接口的,如果被代理对象没有接口将不能使用动态代理技术
public class ProxyTest {
@Test
public void test() {
System.out.println("——————————");
PersonService ps = new PersonServiceImp();
User login2 = ps.login();
ps.regist();
System.out.println("——————————");
/*
* loader: 类加载器
* interfaces: 被代理对象所有的父接口
* InvocationHandler: 代理后的增强方法的封装形式
*/
PersonService psProxy = (PersonService) Proxy.newProxyInstance(PersonServiceImp.class.getClassLoader(), PersonServiceImp.class.getInterfaces(),
new InvocationHandler() {
@Override
/*
* proxy:增强后的对象-代理对象
* method:要通过代理对象增强的方法
* args:执行原方法的参数
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置通知
System.out.println("开启事务OpenTransfaction");
//连接点
Object res = method.invoke(ps, args);
// 后置通知
System.out.println("提交事务Commit");
return res;
}
});
User login = psProxy.login();
psProxy.regist();
}
}
cglib代理
第三方代理技术,cglib代理.当被代理对象没有父接口的时候则需要选择这种代理方式.代理的原理是对目标对象进行继承代理. 如果目标对象被final修饰.那么该类无法被cglib代理.
public class ProxyTest2 {
public static void main(String[] args) {
Enhancer eh = new Enhancer();
// 1.设置父类
eh.setSuperclass(UserServiceImpl.class);
// 2.增强代码
/**
** arg0:代理对象
** arg1:原方法
** arg2:方法参数列表
** arg3:代理后的子类方法对象
**/
eh.setCallback((MethodInterceptor) (arg0, arg1, arg2, arg3) -> {
// 前通知
System.out.println("开启事务");
// 原来方法调用
Object re = arg3.invokeSuper(arg0, arg2);
// 后通知
System.out.println("提交事务");
return re;
});
// 3.创建对象
UserServiceImpl us = (UserServiceImpl) eh.create();
us.register();
System.out.println(us instanceof UserServiceImpl);
}
}