AOP概述
- AOP:
Aspect Oriented Programming面向切面编程,是OOP(面向对象编程)的延续,利用AOP可以对业务逻辑的各个部分进行隔离,从而使业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发效率。 - AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视,事务管理,安全检查,缓存)
AOP 底层实现
代理模式
Spring框架的AOP技术底层是采用的代理模式,代理方式提供了两种
-
基于JDK的动态代理:必须是面向接口的,只有实现了具体接口的类才能生成代理对象
JDK的动态代理主要涉及java.lang.reflect中的Proxy和InvocationHandler两个类。InvocationHandler是个接口,可以通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态地将横切逻辑和业务逻辑编制在一起。 -
基于CGLIB动态代理:对于没有实现了接口的类,采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截所有父类方法的调用并顺势织入横切逻辑。
JDK动态代理
//使用Proxy类生成对象
public class MyProxyUtils {
public static UserDao getProxy(final UserDao dao) {
// 1:类加载器 2:传入的类实现的接口 3:匿名内部类
UserDao proxyUser = (UserDao) Proxy.newProxyInstance(dao.getClass().getClassLoader(), dao.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("save"))
System.out.println("记录日志...");
return method.invoke(dao,args);
}
});
//返回代理对象
return proxyUser;
}
}
/******************* Test ********************************/
public class test{
@Test
public void run(){
UserDao userDao=new UserDaoIMpl();
//工具类获取代理对象
UserDao proxy=MyProxyUtils.getProxy(userDao);
//调用代理对象方法
....
}
}
CGLib 动态代理
public class MyCgilbUtils {
public static BookDaoImpl getProxy(){
Enhancer enhancer=new Enhancer();
//设置父类
enhancer.setSuperclass(BookDaoImpl.class);
//设置回调函数
enhancer.setCallback(new MethodInterceptor() {
//代理方法对象的执行,回调函数就会执行
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//正常执行
if(method.getName().equals("save"))
System.out.println("记录日志...");
return methodProxy.invokeSuper(o,objects);
}
});
//生成代理对象
BookDaoImpl proxy=(BookDaoImpl) enhancer.create();
return proxy;
}
}
/******************* Test ********************************/
public class test{
@Test
public void run(){
//生成代理对象
BookDaoImpl proxy=MyCgilbUtils.getProxy();
//调用代理对象方法
....
}
}
用户可以通过getProxy()方法为一个类创建动态代理对象。
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)是CGLib定义的Intercptor接口方法,它拦截所有目标类方法的调用,其中Object 表示目标实例,Method为目标类方法的反射对象,objects为方法的动态入参,MethodProxy 为代理实例。
总结
CGLib所创建的动态代理对象的性能依旧比JDK所创建的动态代理对象的性能高大约10倍,当时CGLib在创建代理对象的时所花费的时间却比JDK动态代理多大概8倍。对于singleton的代理对象或者具有实例池的代理,因为无须频繁得创建代理对象,所以比较适合采用CGLib动态代理技术,反正则适合采用JDK动态代理技术。
AOP相关术语
public class UserDaoImpl {
public void save(){}
public void update(){}
public void delete(){}
}
-
Joinpoint连接点:所谓连接点是指那些被拦截到的点UserDaoImpl中所有的方法都可以成为连接点save、update、delete -
Pointcut切入点:所谓切入点就是我们要对哪些Joinpoint进行拦截的定义拦截哪个方法(对哪个方法做增强)
save、update -
Advice通知/增强:所谓通知是指拦截到Joinpoint之后要做的事情例如要增加一个记录日志的
log()方法 -
Introduction(引介):是一种特殊的通知,在不修改代码的前提下,Introduction可以在运行期为类动态地添加一些方法或者Field -
Target目标对象:代理的目标对象,例如,UserDaoImpl -
Weaving织入:把通知添加到目标对象,生成代理对象的过程Spring采用动态代理织入,
AspcetJ采用编译期织入和类装载期织入 -
Proxy代理:生成的代理对象 -
Aspect切面:切入点+通知=切面,通知需要自己编写,切入点需要配置
AOP:通知
定义:切面也需要完成工作,在AOP术语中,切面的工作被称为通知
工作内容:通知定义了切面是什么以及何时使用,除了描述切面要完成的工作,通知还解决合适执行这个工作
通知类型:
- 前置通知:在目标方法执行之前执行
- 后置通知:在目标方法执行之后执行
- 环绕通知:在目标方法执行前和执行后执行
- 异常抛出通知:在目标方法执行出现异常的时候执行
- 最终通知:无论目标方法是否出现异常,最终通知都会执行
AOP:切入点表达式
execution( [方法访问修饰符] 方法返回值 包名.类名.方法名(方法的参数) )
完整写法:execution(public void gongfukangee.Demo03.CustomerDaoImpl.save())
省略写法:execution(* *..*.*DaoImpl.*save(..))
execution()固定的public可以省略不写- 返回值 可以使用通配符
*,表示任意的返回值,返回值类型不能不写 - 包名 可以使用
*替代 简写*..* *DaoImpl所有以DaoImpl结尾的类saev*()所有以save开头的方法- 方法参数:
(..) * *..*.*DaoImpl.save*(..)
下一篇:Spring学习笔记[5]之AOP入门程序 https://blog.youkuaiyun.com/Rabbit_Judy/article/details/81842600
本文介绍了面向切面编程(AOP)的概念及其如何通过代理模式实现业务逻辑的解耦。详细探讨了Spring框架中AOP的两种代理实现:基于JDK的动态代理和基于CGLIB的动态代理。并通过示例代码展示了这两种代理的具体应用。
1061

被折叠的 条评论
为什么被折叠?



