springAOP与springIOC共同成为spring框架的核心技术,AOP是面向切面编程,切面是什么?以我的个人理解来说,aop要做的事情其实是把一个从上到下的流水线(例如:浏览器页面访问—>Tomcat—>controller—>service—>dao—>数据库)中的某些可以被不同层级去使用的功能或者事务借助xml文件的中间作用,将它们拿出来与主业务分开编程(拿出来被单独编程之后的方法与它原来的主业务属于同一层级但不属于同一主线,所以称为切面,是一个被增强的方法与增强方法组成的面,形象一点就是一把水平切过来的刀,这个描述与c语言里的函数有着相似的性质,我看到了一些面向过程的影子),实现解耦合与功能增强以及可维护性的提升。例如日志,记录某些功能的访问次数,记录订单的取消次数,商品的浏览次数等等都属于面向切面编程的技术。
那么进入主题,为了加深我对于AOP的理解,它的底层实现,动态代理技术:
基于jdk的动态代理(借助接口来生成代理对象)
1、目标对象:
public class target implements targetInterface{
@Override
public void save() {
System.out.println("目标对象的功能save执行.....");
}
}
2、增强:
public class advice {
public void before(){
System.out.println("前置增强");
}
public void after(){
System.out.println("后置增强");
}
}
3、目标对象实现的接口(也可能有多实现):
public interface targetInterface {
void save();
}
4、测试用接口生成代理对象并调用目标对象的save方法:
public class test {
//基于jdk的动态代理,AOP的底层原理之一,为了加深理解,spring会有封装!
public static void main(String[] args) {
//目标对象的创建,模拟功能
target target = new target();
//获得写好的增强方法,模拟一下日志控制
advice advice = new advice();
//返回值是动态生成的代理对象,用接口接一下形成代理对象pro,jdk的动态代理对象pro与目标对象target属于兄弟关系
targetInterface pro = (targetInterface) Proxy.newProxyInstance(
//目标对象的类加载器,java反射中的知识
target.getClass().getClassLoader(),
//目标对象相同的字节码对象数组(java的单继承多实现特性,一个对象可能实现多个接口)
target.getClass().getInterfaces(),
new InvocationHandler() {
//这个invoke就是调用代理对象的任何方法都是执行这个invoke方法中
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
advice.before();
Object invoke = method.invoke(target, args);
advice.after();
return invoke;
}
}
);
//调用代理对象的方法
pro.save();
}
}
5、控制台结果:
基于cglib的动态代理(个人觉得对于这块自己得扩展认知,加深理解)
除了没有接口,不一样的就是生成代理对象的测试方法以及需要导入cglib的坐标,但是在spring-context的jar包中我发现spring框架已经封装好了关于cglib的相关jar包:
所以我们直接写测试方法:
public class test {
//基于cglib的动态代理,一样不需要写,spring会对其用一定的封装!
public static void main(String[] args) {
//目标对象
target target = new target();
//增强对象
advice advice = new advice();
//返回的是动态代理对象,基于cglib生成,与target属于师徒关系(绝对不是继承,用反射实现,没有血缘关系)
//1,创建增强器
Enhancer enhancer = new Enhancer();
//2,设置父类
enhancer.setSuperclass(target.class);
//3,设置回调函数
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//执行前置
advice.before();
//执行目标
Object invoke = method.invoke(target, objects);
//执行后置
advice.after();
return invoke;
}
});
//4,生成代理对象,用目标对象类型接,因为不基于接口,属于师徒关系
target pro = (target) enhancer.create();
pro.save();
}
}
结果:
附上学习AOP必须先知道的相关术语:
- Target(目标对象):代理的目标对象。
- Proxy (代理):一个类被 AOP 织入增强后,就产生一个结果代理类。
- Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点。
- Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。
- Advice(通知/ 增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。
- Aspect(切面):是切入点和通知(引介)的结合。
- Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。