接着Spring第五篇讲 我们今天将叙述以下几个知识点
1 什么是AOP
AOP 是一种思想 横向重复 纵向抽取
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。 AOP 解决 OOP 中遇到的一些问题.是 OOP 的延续和扩展.
2 为啥学习AOP
对程序进行增强,不改变源码的前提下 AOP 可进行权限校验,日志记录,性能监控,事物控制等功能。
3 Spring中AOP的由来
AOP 最早是由AOP联盟提出来的,并且制定了规范 Spring框架引入aop思想 必须遵守AOP联盟的规范
Spring中能够为容器中管理对象生成动态代理对象(以前自己写代码) spring能帮我们生成动态代理对象----》完成spring思想来开发。
4 Spring实现aop原理
就是动态代理技术和cglib技术
动态代理技术 被代理对象必须实现接口才能产生代理对象
cglib可以对所有类进行代理 但是如果该类被final修饰则无法被cglib代理
5 aop名词(相关术语)
5.1 Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的连接点.5.1
5.2 Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义.指的就是已经发生的
5.3 Advice(通知/增强):增强的代码 所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
写好一个“通知” 把这些“通知” “切入”到“连接点”
5.4 Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类动态地添加一些方法或 Field.
5.5Target(目标对象):代理的目标对象(被代理对象)
5.6 Weaving(织入):是将通知 织入 切入点 过程 叫织入 是指把增强应用到目标对象来创建新的代理对象的过程. spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装在期织入
5.7 Proxy(代理): 将通知织如到目标对象之后,形成代理对象, 一个类被 AOP 织入增强后,就产生一个结果代理类Aspect(切面): 是切入点和通知(引介)的结合
5.8 aspect 切入点+通知
6 Spring中如何使用AOP
6.1 xml配置
6.1.1 导包
4+2+2+2
前六个包在前几次spring中已经提过 说后面两个2 分别是
后面的2 是aop联盟包 如下图
下的
第二个包 在搜索框搜 weaver
6.1.2 准备目标对象 代码如下
@Override
public void save() {
System.out.println("存储李俊");
}
@Override
public void delete() {
System.out.println("删除账户");
}
@Override
public void update() {
System.out.println("更新账户");
}
@Override
public void find() {
System.out.println("查找用户");
}
6.1.3 准备通知(advice) 建类myAdvice 代码如下
public void before(){
System.out.println("这是前置通知");
}
public void afterReturning(){
System.out.println("这是后置通知 如果出现异常不会调用");
}
//环绕通知
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("这是环绕通知之前的部分!!");
Object proceed = pjp.proceed();//调用目标方法
System.out.println("这是环绕通知之后的部分!!");
return proceed;
}
public void afterException(){
System.out.println("出事啦!出现异常了!!");
}
//后置通知
public void after(){
System.out.println("这是后置通知(出现异常也会调用)!!");
}
其中环绕通知 需要特别记住。
6.1.4 写配置文件 将通知织入目标对象中 需要进行新的约束引入 代码如下
<!-- 1 配置目标对象 -->
<bean name="User" class="lijun.Service.UserServieImpl"></bean>
<!-- 2 配置通知对象 -->
<bean name="myAdvice" class="cn.lijun.springaop.MyAdvice"></bean>
<!-- 3将通知 织入 目标 -->
<aop:config>
<aop:pointcut expression="execution(* cn.lijun.Service.*ServiceImpl.*(..))" id="lj"/>
<aop:aspect ref="MyAdvice">
<!-- 指定名为before方法作为前置通知 -->
<aop:before method="before" pointcut-ref="lj" />
<!-- 后置 -->
<aop:after-returning method="afterReturning" pointcut-ref="lj" />
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="lj" />
<!-- 异常拦截通知 -->
<aop:after-throwing method="afterException" pointcut-ref="lj"/>
<!-- 后置 -->
<aop:after method="after" pointcut-ref="lj"/>
</aop:aspect>
</aop:config>
</beans>
6.1.5 测试
package cn.lijun.springaop;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.lijun.Service.UserService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:cn/lijun/springaop/applicationContext.xml")
public class Demo {
@Resource(name="User")
private UserService u;
@Test
public void fun1(){
u.save();
}
}
6.2 注解配置 和上面类似。