<>什么是AOP

* AOP:Aspect Oriented Programing(面向切面编程)
* 采用横向抽取机制,取代传统继承体系重复性代码(性能监视、事务管理、安全检查、缓存)即代理机制
* 使用纯JAVA实现,不需要专门的编写过程和类加载器,在运行期通过代理方式向目标织入增强代码
<>AOP相关术语

* Joinpoint(连接点):所谓连接点是指那些可以被拦截到的点。在Spring中,这些点指的是方法,因为spring只支持方法类型的连接点。
* Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义;个人理解:一个要拦截或者已经被拦截的方法被称为一个切入点。
* Advice(通知/增强):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知。个人理解:对方法进行拦截之后所做的增强方法就是通知
,分为前置通知,后置通知,异常通知,最终通知,环绕通知。
*
Introduction(引介):是一种特殊的通知在不修改类代码的前提下,Introduction可以在运行期为类动态的添加一些方法和Field。(一般一研究)
* Target(目标对象)代理的目标对象。
*
**Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。**spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入
* Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类
* Aspect(切面):是切入点和通知(引介)的结合

<>JDK动态代理
========interface======== public interface UserDao { public void save(); public
void update(); public void delete(); public void find(); } ========UserDaoImpl==
====== public class UserDaoImpl implements UserDao { public void save() { System
.out.println("保存用户..."); } public void update() { System.out.println("修改用户...");
} public void delete() { System.out.println("删除用户..."); } public void find() {
System.out.println("查询用户..."); } } ========MyJdkProxy======== public class
MyJdkProxy implements InvocationHandler{ private UserDao userDao; public
MyJdkProxy(UserDao userDao){ this.userDao = userDao; } public Object createProxy
(){ Object proxy = Proxy.newProxyInstance(userDao.getClass().getClassLoader(),
userDao.getClass().getInterfaces(),this); return proxy; } public Object invoke(
Object proxy, Method method, Object[] args) throws Throwable { if("save".equals(
method.getName())){ System.out.println("权限校验..."); return method.invoke(userDao,
args); } return method.invoke(userDao,args); } ========Test========= @Test
public void demo1(){ UserDao userDao = new UserDaoImpl(); UserDao proxy = (
UserDao)new MyJdkProxy(userDao).createProxy(); proxy.save(); proxy.update();
proxy.delete(); proxy.find(); } }
<>CGLIB生成代理

* 生成了一个类,来继承这个目标类
* 对于不使用接口的业务类,无法使用JDK动态代理
* CGlib采用非常底层字节码技术,可以为一个类动态的增加一些方法也可以生成一个类去继承这个类,解决无接口代理问题 ========ProdectDao
======== public class ProdectDao { public void save(){ System.out.println(
"保存商品...."); } public void update(){ System.out.println("修改商品...."); } public
void find(){ System.out.println("删除商品...."); } public void delete(){ System.out.
println("查询商品...."); } } ========MyCglibPorxy======== public class MyCglibPorxy
implements MethodInterceptor { private ProdectDao prodectDao; public
MyCglibPorxy(ProdectDao prodectDao){ this.prodectDao=prodectDao; } public Object
createProxy(){ //1.创建核心类 Enhancer enhancer = new Enhancer(); //2.设置父类 enhancer.
setSuperclass(prodectDao.getClass()); //3.设置回调 enhancer.setCallback(this);
//4.生成代理 Object proxy = enhancer.create(); return proxy; } @Override public
Object intercept(Object proxy, Method method, Object[] args, MethodProxy
methodProxy) throws Throwable { if ("save".equals(method.getName())) { System.
out.println("权限校验...."); return methodProxy.invokeSuper(proxy,args); } return
methodProxy.invokeSuper(proxy,args); } } ========Test======== @Test public void
demo1(){ ProdectDao prodectDao = new ProdectDao(); ProdectDao porxy = (
ProdectDao) new MyCglibPorxy(prodectDao).createProxy(); porxy.save(); porxy.find
(); porxy.update(); porxy.delete(); }
<>总结

* Spring在运行期,生成动态代理对象,不需要特殊的编译器
* Spring AOP的底层就是通过JDK动态代理或CGLib动态代理技术 为目标Bean执行横向织入
1.若目标对象实现了若干接口,spring使用JDK的动态代理
2.若目标对象没有实现任何接口,spring使用CGLIB动态代理
* 程序中应优先对接口创建代理,便于程序解耦维护
* 标记为final的方法,不能被代理,因为无法进行覆盖
* JDK动态代理,是针对接口生成子类,接口中方法不能使用final修饰
* CGLib是针对目标类生产子类,因此类或方法不能使用final修饰
* Spring支持方法连接点,不提供属性的连接点

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信