AOP面向切面编程
1.AOP概念和作用1.1概念它是一种编程范式用于指导开发者如何组织程序结构1.2.作用在不惊动原始设计的基础上对其进行功能代码增强1.3.底层通过动态代理来实现的Spring官方提供了两种代理方式JDK和第三方cglib 所以AOP就是为了简化动态代理开发1.4AOP的核心概念切入点Pointcut定义(通过表达式或注解)哪些方法需要被增强例如:update()、delete()方法select()方法没有被增强所以不是切入点但是是连接点。连接点JoinPoint被增强的方法(可能被织入的地方)例如update()、delete()、select()等都是连接点。通知Advice也就是在切入点目标方法前后需要执行的增强代码操作一般都是需要增强的公共功能代码在SpringAOP中增强代码操作都是以方法的形式呈现也就是需要将增强的代码封装为方法通知类通知方法所在的类叫做通知类该通知类一般最终会升级为切面类切面Aspect描述通知与切入点的对应关系一般都是一个Java类旧的配置模式中就是一个xml文件在该切面类中进行配置描述哪些通知方法对应哪些切入点方法。举例Spring AOP实现方法调用前后打印日志首先就是创建一个业务服务类用于模拟一些业务方法再定义一个切面类用来封装日志记录的一些逻辑使用切入点和通知确定需要增强的代码操作再业务类中再用连接点插入日志记录的代码2.AOP工作流程2.1工作流程1.使用Spring容器进行启动2.读取所有切面配置中的切入点所有的切面配置类都进行了IOC开发3.初始化目标Bean也就是被增强的类判定bean对应的类中的方法是否匹配到任意切入点匹配失败创建原始对象匹配成功创建原始对象目标对象的代理对象4.获取bean执行方法获取的bean是原始对象时调用方法并执行完成操作获取的bean是代理对象时根据代理对象的运行模式运行原始方法与增强的内容完成操作2.2知识点拆开目标对象Target被代理的对象也叫原始对象该对象中的方法没有任何功能增强。 代理对象Proxy代理后生成的对象由Spring帮我们创建代理对象。Spring框架底层创建代理对象方式选择两种方式1如果目标对象实现了任意接口就使用JDK方式创建代理对象使用Proxy类创建代理对象2如果目标对象没有实现任意接口就使用第三方cglib方式创建代理对象使用Enhancer类创建代理对象3.切入点理解切入点匹配要进行增强的方法切入点表达式要进行增强的方法的描述方式描述方式一执行com.yaorange.service包下的BookService接口中的无参数save方法execution(void com.yaorange.service.BookService.save())描述方式二执行void com.yaorange.service.impl包下的BookDaoImpl类中的无参数save方法execution(void com.yaorange.service.impl.BookServiceImpl.save())切入点表达式标准格式动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数类型列表) 异常名修饰符可以省略动作关键字(返回值 包名.类/接口名.方法名(参数类型列表) 异常名通配符目的可以使用通配符描述切入点快速描述。*表示单个任意符号可以独立出现也可以作为前缀或者后缀的匹配符出现.. 标识多个连续的任意符号可以独立出现常用于简化包名与参数的书写参考写法一般包名会完整指定目的提高框架的查找效率业务方法开发隐式规则方法名建议使用统一前缀如查询使用get开发新增使用add开头修改使用update开头删除使用remove开头*表示任意但是必须有内容..表示任意有无均可//匹配com.yaorange.service.impl包中所有以ServiceImpl结尾的接口类中所有get开头方法方法参数任意//匹配指定包中多个类中多个方法Pointcut(execution(* com.yaorange.service.impl.*ServiceImpl.get*(..)))public void pt(){}//匹配指定包中多个类中所有方法Pointcut(execution(* com.yaorange.service.impl.*ServiceImpl.*(..)))public void pt(){}//匹配指定包中所有类中所有方法Pointcut(execution(* com.yaorange.service.impl.*.*(..)))public void pt(){}4。基于注解开发4.2.1 开发步骤1自定义注解注意点1.Target需要开发者根据需要选择注解可用位置ElementType.TYPE类上使用ElementType.METHOD方法上使用2.注解属性定义语句是基于方法级default指定默认返回值Target({ElementType.TYPE,ElementType.METHOD})Retention(RetentionPolicy.RUNTIME)Documentedpublic interface Log {//在注解中定义的属性是用于反射时获取属性值进行逻辑判断注解属性照顾是基于getXXX获取的//实际应用参考后期若依项目环境已有功能学习后期模拟面试必须能说明罚款10元班费//语法 数据类型 属性名() default 默认值;//如 String title() default ;// int code() default 1;}2在开发切入点的注解中关联自定义注解语法Pointcut(annotation(自定义注解的路径))Pointcut(annotation(com.yaorange.annotation.Log))public void pt(){}//切入点方法是空方法3在需要被增强的方法上使用自定义标识Logpublic void save() {System.out.println(book service save ...);}4.AOP通知类型4.1分类前置通知在切入点方法执行之前执行后置通知在切入点方法执行之后执行如果切入点方法内部出现异常将不会执行。异常通知在切入点方法执行之后执行只有当切入点方法内部出现异常之后才执行。最终通知在切入点方法执行之后执行无论切入点方法内部是否出现异常最终通知都会执行。环绕通知(重点)手动调用切入点方法并对其进行增强的通知方式。4.2通知详解4.2.1 前置通知名称Before类型方法注解位置通知方法定义上方作用设置当前通知方法与切入点之间的绑定关系当前通知方法在原始切入点方法前运行例Before(pt())public void before() {System.out.println(before advice ...);}4.2.2 最终通知名称After类型方法注解位置通知方法定义上方作用设置当前通知方法与切入点之间的绑定关系当前通知方法在原始切入点方法后不管是否出现异常运行After(pt())public void after() {System.out.println(after advice ...);}4.2.3 后置通知名称AfterReturning类型方法注解位置通知方法定义上方作用设置当前通知方法与切入点之间的绑定关系当前通知方法在原始切入点方法正常执行后运行AfterReturning(pt())public void afterReturning() {System.out.println(afterReturning advice ...);}4.2.4 异常通知名称AfterThrowing了解类型方法注解位置通知方法定义上方作用设置当前通知方法与切入点之间的绑定关系当前通知方法在原始切入点方法运行抛出异常后执行AfterThrowing(pt())public void afterThrowing() {System.out.println(afterThrowing advice ...);}5.2.5 环绕通知名称Around类型方法注解位置通知方法定义上方作用设置当前通知方法与切入点之间的绑定关系当前通知方法在原始切入点方法前后运行特点被标识方法必须定义ProceedingJoinPoint参数,ProceedingJoinPoint框架在执行该方法时会自动给参数依赖注入通过参数对象可以操控目标方法Around(pt())public Object around(ProceedingJoinPoint pjp) throws Throwable {System.out.println(around before advice ...);Object rs pjp.proceed();//Object[] args pjp.getArgs();//获取调用目标方法时传入的参数值// 省略对args参数值进行调整//Object rs pjp.proceed(args);//只有需要对目标方法执行的参数值进行调整时才使用有参数的执行方法System.out.println(around after advice ...);return rs;}环绕通知注意事项环绕通知方法形参必须是ProceedingJoinPoint表示正在执行的连接点使用该对象的proceed()方法表示对原始对象方法进行调用返回值为原始对象方法的返回值。环绕通知方法的返回值建议写成Object类型用于将原始对象方法的返回值进行返回哪里使用代理对象就返回到哪里。5.Spring事务管理1.事务管理简介1.1作用事务作用保障一系列的数据库sql操作要么全部成功要么全部失败Spring事务管理作用在业务层保障一系列的数据库操作同成功同失败业务方法中同时调用多个mapper接口方法Spring的事务管理开发者在Spring配置类中开启事务支持并配置事务管理器IOC配置开发者需要在对应的业务方法上使用事务管理注解该注解也就是一个切入点注解由官方提供框架底层基于事务管理器Spring官方开发的类提供的方法对业务层目标方向进行事务控制如事务提交事务回滚...官方是通过AOP思想完成事务控制方法的增强执行Spring事务管理配置重点【第一步】开启事务管理注解底层驱动使用注解EnableTransactionManagement【第二步】设置事务管理器(将事务管理器添加到IOC容器中)说明可以直接在SpringConfig中配置事务管理器也可以单独新增配置类配置ConfigurationComponentScan({com.yaorange.service.impl})EnableTransactionManagement//开启Spring的事务管理提供事务注解的底层实现Import({JdbcConfig.class,MyBatisConfig.class})public class SpringConfig {//配置事务管理器Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource){DataSourceTransactionManager transactionManager new DataSourceTransactionManager();transactionManager.setDataSource(dataSource);return transactionManager;}}注意事项事务管理器要根据实现技术进行选择基于MyBatis框架需要使用DataSourceTransactionManagerMyBatis框架使用的是JDBC事务transactionManager typeJDBC【第三步】在业务层实现类上或方法添加Spring事务管理注解开发建议初期开发时可以在类上直接使用注解后期代码优化时将注解移植到有更新操作的业务方法上注意事项注解式事务可以添加到业务方法上表示当前方法开启事务也可以添加到类上表示当前类中所有方法开启事务实际开发中建议给包含更新操作的业务方法添加注解6.Spring事务角色6.1 Spring事务角色事务管理员发起事务方在Spring中通常指代业务层开启事务的方法事务协调员加入事务方在Spring中通常指代数据层方法也可以是其他业务类的方法6.2 事务传播行为