一.AOP
AOP(Aspect Oriented Programing)面向切面编程,一种软件工程的编程范式
OOP(Object Oriented Programing)面向对象编程:制作程序时,设计模型,运行时,靠对象运行,是一种软工的编程范式
AOP联盟:一个组织,致力于AOP的发展研究JRC
AOP经典应用:性能监视、事务管理、安全检查(权限管理)、缓存等
Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码
AspectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ 扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入
AOP思想:AOP关注的是程序中的共性功能,开发时,将共性功能抽取出来制作成独立的功能模块,此时原始功能中将不具有这些被抽取出的共性功能代码。在当时具有被抽取的共性功能的模块运行时候,将共性功能,模块进行运行,即可完成原始的功能。
优点:加强代码的复用性,同时程序开发时可以只考虑个性化的功能,不需要考虑共性功能
二.基本概念
●连接点(Joinpoint):具有特定功能的方法,一般方法(类中的方法)
●切入点(Pointcut):具有共性功能的方法的统称一种称呼方式
●目标对象(Target Object):包含切入点的类
●通知(Advice):将共性功能抽取走,制作成独立的功能模块
●切面(Aspect):切入点与通知匹配的一种情况
●AOP代理(AOP Proxy):运行过程使用AOP创建代理对象进行运行,运行过程中将抽取的功能执
行该过程由AOP自动完成,所以称为AOP代理
●织入(Weaving):称将抽取的功能加入原始功能运行的整个过程叫做织入(动态)织入控制的是字
节码
●引入(Introduction):完整的方法或成员变量抽取加入的过程叫做引入
工作流程:
开发时,制作功能类(目标对象),将其中的方法中的通用功能(通知)抽取出来,制作成独立的类(通知类),原始目标对象中的方法(切入点)不再进行通用功能的制作。该功能被抽取后,无法完成完整的业务逻辑,需要在运行时将通知加入到对应的位置执行。为了完成此操作,必须将切入点与通知进行一对一的对应关系设定(切面)。
运行流程:
运行时,Spring一直监控切面中所配置的切入点对应的方法的执行,发现执行了该方法,使用AOP的代理机制,创建代理对象(AOP代理),将原始方法(切入点)与通知进行融合,形成一个完整的业务逻辑进行运行,此过程称为织入。
AOP实现原理
●接口+ 实现类:采用JDK “动态代理”生产代理对象
●实现类:采用字节码增强框架cglib
三.XML开发AOP
1.jar包
Spring核心包(4个)
Spring日志包(2个)
AOP包(4个)
Spring进行AOP开发(1个)(3.2资源包)
spring-aop-3.2.0.RELEASE.jar
Spring整合AspectJ框架(3.2资源包)
spring-aspects-3.2.0.RELEASE.jar
AOP联盟规范(1个) (3.0.2依赖包)
https://www.wendangku.net/doc/b412040813.html,.aopalliance-1.0.0.jar
aspectJ支持(1个) (3.0.2依赖包)
https://www.wendangku.net/doc/b412040813.html,.aspectj.weaver-1.6.8.RELEASE.jar
2.制作目标对象
//目标对象类
public class UserService {
//连接点//切入点
public void add(){
//共性功能被抽取走了,放入到了MyAdvice类中的fn方法里
System.out.println("add");
}
//连接点
public void delete(){
System.out.println("bbbbbb");
System.out.println("delete");
}
}
3.制作通知
//通知类
public class MyAdvice {
//具有共性功能的方法:通知
public void fn(){
//共性功能
System.out.println("aaaaa");
}
}
4. 开启AOP空间支持
xmlns:xsi="https://www.wendangku.net/doc/b412040813.html,/2001/XMLSchema-instance" xmlns:aop="https://www.wendangku.net/doc/b412040813.html,/schema/aop" xsi:schemaLocation=" https://www.wendangku.net/doc/b412040813.html,/schema/beans https://www.wendangku.net/doc/b412040813.html,/schema/beans/spring-beans.xsd https://www.wendangku.net/doc/b412040813.html,/schema/aop https://www.wendangku.net/doc/b412040813.html,/schema/aop/spring-aop.xsd ">
5. 配置切面:切入点与通知之间的关系
method="fn" pointcut="execution(public void https://www.wendangku.net/doc/b412040813.html,erService.add())" /> 6.运行时必须使用Spring的格式 public class AopApp { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService service = (UserService) ctx.getBean("userService"); service.add(5); } } 四.切入点表达式 1.execution:表示执行某个切入点方法(常用) ?格式:execution(方法格式表达式) ?例一:匹配所有指定返回值类型的方法 ?void *(..) i nt *(..) double *(..) ?例二:匹配指定包或子包中类的方法 ?*..*() https://www.wendangku.net/doc/b412040813.html,er.dao.*.*(..) cn..dao.*.*(..) ?例三:匹配指定类或接口的方法 ?* *https://www.wendangku.net/doc/b412040813.html,erImpl.*(..) * *..*Impl.*(..) * *..*DAO.*(..) ?例四:匹配指定方法名或部分匹配方法名的方法 ?*..*.add(..) *..*.*e*(..) *..*.get*(..) ?例五:匹配所有指定参数个数或类型的方法 2.格式: “execution( [方法访问控制修饰符] 返回值类型包名.类名.方法名(参数列表)) ” 3.切入点可以配置接口,运行时走实现类 4.切入点可以配置成公共的 五.通知类别 before:前置通知(应用:各种校验) 在方法执行前执行,如果其中抛出异常:在异常前执行 after:后通知(应用:清理现场) 方法执行完毕后执行,无论方法中是否出现异常:都执行 afterReturning:返回后通知(应用:常规数据处理) 方法正常返回后执行,如果方法中抛出异常:无法执行 afterThrowing:抛出异常后通知(应用:包装异常信息) 方法抛出异常后执行,如果方法没有抛出异常,无法执行 around:环绕通知(应用:十分强大,可以做任何事情) 方法执行前后分别执行,可以阻止方法的执行 //环绕通知 public void around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("around before......"); //调用原始方法 pjp.proceed(); System.out.println("around after......"); } 1.通知的配置格式 2.通知顺序:与配置顺序有关 多个切面间 先声明的before先运行, 后声明的before后运行 先声明的after后运行 后声明的after先运行 总结:配置时以最终运行顺序为准 总结: AOP:关注共性功能的开发 共性功能抽出,运行时原始功能错误,必须加入共性功能,原始对象已经无法完成该功能,AOP代理负责创建一个新的对象,该对象完成原始功能,通过织入操作完成。 Spring加载上下文时,会读取AOP的配置aop:config,Spring已经知道了哪些方法需要被监控,由切入点实现,当被监控的方法运行时,完成上面一段的操作,加入的功能需要根据配置完成。 织入:A模块中缺少B功能BA A.class 编译期植入:A.class中对应的功能已经有BA 类加载期植入:A.class中不具有B功能,但是加载A.class时,内存中的类A.class具有B功能 运行期植入:执行到时,添加(Spring实现) 六.AOP通知参数 如果需要在通知方法中获取原始方法的调用参数,需要在通知方法的第一个形参位置声明JoinPoint 类型的参数,使用该参数调用getArgs()方法可以获得原始方法的调用参数列表Object[] public void before(JoinPoint jp){ Object[] objs = jp.getArgs(); System.out.println("before......"+objs[0]+","+objs[1]); } 所有的通知类别均可获取原始方法调用参数 七.AOP通知返回值 1.只有afterReturning 与around可以获取方法的返回值 2.afterReturning:在配置中设置returning属性,值是变量名的值,与方法的形参进行对应 public void afterReturning(JoinPoint jp,Object abc){ System.out.println("afterReturning......"+abc); } 3.around:直接通过程序中的原始方法调用获取,该方法返回值即为原始方法的返回值 public Object around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("around before......"); //调用原始方法 Object obj = pjp.proceed(); System.out.println("around after......"+obj); return obj; 说明:对原始方法拦截后,最终的运行返回值取决于这里} 八、AOP切面 AOP切面描述的一组切入点与通知方法之间的绑定关系 一个AOP配置中,可以使用多个切面 九、AspectJ AOP框架 介绍 ●AspectJ是一个基于Java语言的AOP框架 ●Spring2.0以后新增了对AspectJ切点表达式支持 ●@AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面●新版本Spring框架,建议使用AspectJ方式来开发AOP ●AspectJ 开发中,一般进行自定义内容编写,及需要进行功能增强,编写AOP。 ●导入jar包 ● 十、AOP注解开发(重点) ●使用注解开发AOP要保障所有的相关类必须受到Spring控制,因此在进行注解开发AOP之前, 首先将所有相关类配置成Bean ?配置式 ?注解式 ? ? ? ? ? 步骤: 1.开启AOP注解配置支持 2.将所有AOP过程中的资源配置成Bean(注解或者XML) 3.在通知对应的类上方声明@Aspect 4.在对应的方法上面声明通知类别,使用5种通知类别注解@Before 5. @Before仅仅定义了通知类别,需要为其指定切入点 @Before("execution(* cn.jiyun.aop.annotation.BookService.add(..))") 知识点一:注解开发公共切入点 //公共切入点配置 public class BookAdvice { @Pointcut("execution(* cn.jiyun.aop.annotation.BookService.add(..))") private void pt(){} @Before("BookAdvice.pt()")…. 知识点二:注解开发通知顺序以实际配置顺序为准 ?around before ?before ?around after ?after ?afterReturning dbcTemplate(了解) 介绍 ●spring 提供用于JDBC开发模板,类似DBUtils。简化JDBC开发。需要手动的编写sql语句。 ●需要数据源(连接池) ●导入jar包: 基本:4+1 jdbc开发:spring-jdbc...jar 、spring-tx...jar(事务) mysql驱动: 连接池:c3p0/dbcp 创建数据库和表 API使用 配置DBCP dao层 spring配置 配置C3P0 spring配置 dao层:查询 使用JdbcDaoSupport dao层 spring配置 事务管理 ●AOP编程经典应用,进行事务管理。 事务:一组业务逻辑操作ABCD,要么全部成功,要么全部不成功。 ●事务特性:4个,ACID 原子性:整体 一致性:数据完整 隔离性:并发(多个事务) 持久性:结果 ●隔离问题:脏读、不可重复读update、虚读(幻读) insert ●隔离级别,为了解决问题 read uncommitted ,读未提交。存在3个问题,解决0个问题。 read committed,读已提交。存在2个问题,解决1个问题(脏读)。 repeatable read,可重复读。存在1个问题,解决2个问题(脏读、不可重复读)。 serializable ,串行化。存在0个问题,解决3个问题。