Spring框架AOP学习总结(下)
目录
@
在Spring框架学习一中主要讲的是一些Spring的概述、Spring工厂、Spring属性注入以及IOC入门,其中最重要的是IOC,上一篇中IOC大概讲的小结一下:
然后呢这一篇中主要讲一下Spring中除了IOC之外的另一个重要的核心:AOP,在Spring中IOC也好,AOP也好,都必须会二者的XML开发以及注解开发,也就是说IOC和AOP的XML开发以及注解开发都要掌握
1、 AOP 的概述
从专业的角度来讲(千万不要问我有多专业,度娘是我表锅不对是表嫂QAQ):
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
从通俗易懂且不失风趣的角度来讲:(来自武哥文章谈谈Spring中的IOC和AOP概念)
面向切面编程的目标就是分离关注点。什么是关注点呢?就是你要做的事,就是关注点。假如你是个公子哥,没啥人生目标,天天就是衣来伸手,饭来张口,整天只知道玩一件事!那么,每天你一睁眼,就光想着吃完饭就去玩(你必须要做的事),但是在玩之前,你还需要穿衣服、穿鞋子、叠好被子、做饭等等等等事情,这些事情就是你的关注点,但是你只想吃饭然后玩,那么怎么办呢?这些事情通通交给别人去干。在你走到饭桌之前,有一个专门的仆人A帮你穿衣服,仆人B帮你穿鞋子,仆人C帮你叠好被子,仆人C帮你做饭,然后你就开始吃饭、去玩(这就是你一天的正事),你干完你的正事之后,回来,然后一系列仆人又开始帮你干这个干那个,然后一天就结束了!
AOP的好处就是你只需要干你的正事,其它事情别人帮你干。也许有一天,你想裸奔,不想穿衣服,那么你把仆人A解雇就是了!也许有一天,出门之前你还想带点钱,那么你再雇一个仆人D专门帮你干取钱的活!这就是AOP。每个人各司其职,灵活组合,达到一种可配置的、可插拔的程序结构。
从Spring的角度看,AOP最大的用途就在于提供了事务管理的能力。事务管理就是一个关注点,你的正事就是去访问数据库,而你不想管事务(太烦),所以,Spring在你访问数据库之前,自动帮你开启事务,当你访问数据库结束之后,自动帮你提交/回滚事务!
1、1 为什么学习 AOP
Spring 的 AOP 的由来:AOP 最早由 AOP 联盟的组织提出的,制定了一套规范.Spring 将 AOP 思想引入到框架中,必须遵守 AOP 联盟的规范.
Aop解决实际开发中的一些问题:
- AOP 解决 OOP 中遇到的一些问题.是 OOP 的延续和扩展.
对程序进行增强:不修改源码的情况下:
- AOP 可以进行权限校验,日志记录,性能监控,事务控制.
1、2 AOP底层实现: 代理机制(了解)
Spring 的 AOP 的底层用到两种代理机制:
- JDK 的动态代理 :针对实现了接口的类产生代理.
- Cglib 的动态代理 :针对没有实现接口的类产生代理. 应用的是底层的字节码增强的技术 生成当前类的子类对象
spring底层会完成自动代理,实现了接口的类默认使用的是JDK 的动态代理,相反的,没有实现接口的类默认使用的是Cglib 的动态代理 ,底层代码可以不懂但这个概念一定要知道,不然会被鄙视的,O(∩_∩)O哈哈~,下面是底层代码,有兴趣的可以了解了解。
JDK 动态代理增强一个类中方法:
public class MyJDKProxy implements InvocationHandler { private UserDao userDao; public MyJDKProxy(UserDao userDao) { this.userDao = userDao; } // 编写工具方法:生成代理: public UserDao createProxy() { UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance(userDao .getClass().getClassLoader(), userDao.getClass() .getInterfaces(), this); return userDaoProxy; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("save".equals(method.getName())) { System.out.println("权限校验================"); } return method.invoke(userDao, args); } }
Cglib 动态代理增强一个类中的方法:
public class MyCglibProxy implements MethodInterceptor { private CustomerDao customerDao; public MyCglibProxy(CustomerDao customerDao) { this.customerDao = customerDao; } // 生成代理的方法: public CustomerDao createProxy() { // 创建 Cglib 的核心类: Enhancer enhancer = new Enhancer(); // 设置父类: enhancer.setSuperclass(CustomerDao.class); // 设置回调: enhancer.setCallback(this);