Spring总结笔记(二)

来源:互联网 发布:电子商务实验室软件 编辑:程序博客网 时间:2024/05/21 19:24
AOP简介
1). 概述 : AOP(Aspect Oriented Programing)面向切面编程 , 是一种编程范式 , 弥补了OOP的不足,基于OOP基础之上进行横向开发
2). AOP主要关注同一层面的各个不同功能模块之间的共性功能 , 将共性功能抽取出来, 做成可插拔式的程序
AOP 与 OOP的区别
OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分
AOP(面向切面编程)则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段


AOP相关术语
目标对象(Target Object) : 指的是需要被增强的对象,由于spring aop是通过代理模式实现,从而这个对象永远是被代理对象
连接点(Joinpoint) : 指类中的方法 , 指那些被拦截到的点
切入点(Pointcut) : 指被抽取了共性功能的方法,也就是后期要增强的方法 ; 切入点一定是连接点, 但连接点不一定是切入点
通知(Advice) : 将共性功能抽取后创建独立的方法称为通知
通知类别 : 被抽取的代码在切入点中的具体位置,称为通知类别
引入(引介)(Introduction) (了解) : 引入机制可以为类添加额外的成员变量或者成员方法,在编译期或类加载期完成的
AOP代理(AOP Proxy) : 最终的对象运行时使用的是代理对象,那么创建代理对象的整个过程称为AOP代理
织入(Weaving) : 将通知加入到切入点对应位置的动作称为织入
切面(Aspect) : 切入点与通知之间的关系


AOP实现介绍(难点)
JDK 实现动态代理 
1). 被代理的类必须实现接口
2). JDK动态代理是针对内存中的Class对象,使用类加载器,动态为目标对象创建代理对象, 增强目标类的功能
3). JDK动态代理是对对象做代理
4). API   1). InvocationHandler  2). Proxy.newProxyInstance(...)
CgLib 动态代理
概述 : 没有实现接口的类, 无法使用动态代理增强功能, 需要使用cglib代理
原理 : cglib采用非常底层字节码技术,可以为一个类创建子类,解决无接口代理问题
步骤
1). 创建内存中的动态类 : Enhancer enhancer = new Enhancer();
2). 内存中动态类继承原始类 : enhancer.setSuperclass(clazz);
3). 设置具体的回调操作 , 进行功能的增强 : enhancer.setCallback(callback);
   1). 创建类实现接口Callback 的子接口MethodInterceptor
   2). methodProxy.invokeSuper(proxy, args); / method.invoke(target, args)
4). 创建内存中动态代理类的对象 : Object proxyObj = enhancer.create();
传统AOP编程(了解)
五种增强接口
1). 前置通知目标方法执行前增强   org.springframework.aop.MethodBeforeAdvice
2). 后置通知目标方法执行后增强   org.springframework.aop.AfterReturningAdvice
3). 环绕通知目标方法执行前后进行增强   org.aopalliance.intercept.MethodInterceptor
4). 异常抛出通知目标方法抛出异常后的增强   org.springframework.aop.ThrowsAdvice
5). 引介通知在目标类中添加一些新的方法或属性(不讲解)    org.springframework.aop.IntroductionInterceptor
配置
1). <bean id="orderServicePointCut" class="org.springframework.aop.support.NameMatchMethodPointcut"> <property name="mappingNames">...</property></bean>
2). <bean id="orderServicePointCut" class="org.springframework.aop.support.JdkRegexpMethodPointcut"><property name="pattern" value=".*Order"></property></bean>
3). <bean class="org.springframework.aop.support.DefaultPointcutAdvisor"></bean>
4).  <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>


传统切点开发 基于AspectJ
1). 配置文件中定义目标和通知的bean
2). 使用aop标签来完成切面与切点声明
<aop:config>
<!-- 定义切点 -->
<aop:pointcut expression="execution(* cn.itheima.aop.IOrderService.*(..))" id="orderServicePointCut" />

<!-- 定义切面 -->
<aop:advisor advice-ref="orderServiceAdvice" pointcut-ref="orderServicePointCut" />
<!-- <aop:aspect></aop:aspect> aspectj框架它定义切面使用的 -->
</aop:config>
<aop:config> : 来声明要对aop进行配置
<aop:pointcut> : 它是用于声明切点(简单说就是对哪些方法进行拦截)
<aop:advisor> : 定义传统的aop的切面,传统的aop切面它只能包含一个切点与一个增强
<aop:aspect> : 定义aspectj框架的切面.,它可以包含多个切点与多个通知


传统开发 切入点表达式
execution 格式定义 :    execution( [修饰符] 返回值 包名.类名.方法名(参数) )
* :代表任意字符
 ..:代表任意数量
常用表达式
1). execution(public void cn.itcast.spring.aop.demo.UserService.add())
2). execution(void cn.itcast.spring.aop.demo.UserService.add())
3). execution(* cn.itcast.spring.aop.demo.UserService.add())
4). execution(* cn.itcast.*.UserService.add())
5). execution(* cn.itcast.*..UserService.add())
6). execution(* cn.itcast.*..UserService.*(int))
7). execution(* *..*())
8). execution(* *..*(..))


Aspectj的通知类型
1). 前置通知Before 相当于BeforeAdvice
2). 后置通知AfterReturning 相当于AfterReturningAdvice
3). 环绕通知 Around 相当于MethodInterceptor
4). 抛出通知AfterThrowing 相当于ThrowAdvice
5). 引介通知DeclareParents 相当于IntroductionInterceptor
6). 最终通知After 不管是否异常,该通知都会执行
通知的执行顺序 : 执行顺序受XML配置文件, 配置的顺序影响, 配置在前面的先运行, 配置在后面的后运行


切入点配置方式
方式一:  <aop:before method="fn1" pointcut="execution(* *..*(..))"/>
方式二:  配置公共的切入点, 配置在<aop:config>这一层 , <aop:pointcut id="pt" expression="execution(....)"/>
方式三: 先配置切入点元素,然后配置参照切入点 , 配置在通知层面<aop:aspect ref="myAdvice">, <aop:pointcut id="pt" expression="execution(....)"/>


AOP通知获取参数
1). 前置通知(before)、后置通知(after)、返回通知(afterReturning)、异常通知(afterThrowing)中方法参数类型:JoinPoint
2). 环绕通知方法参数类型: ProceedingJoinPoint
3). 调用其方法 getArgs() 就可以获取方法执行时传入的参数
4). 注意: JoinPoint 必须为方法形参的第一个参数
5)(了解). execution(* *..add(..)) &amp;&amp; args(a,c) 配置 通知类的方法的形参, 获取传入的参数


代理方式的选择
proxy-target-class
true : 对目标要使用cglib代理
false : 有接口使用proxy代理


注解AOP
1). 开启注解式AOP功能  : <aop:aspectj-autoproxy/>
2). 让资源受spring管理
3). 在通知类上声明该类时一个通知 @Aspect
4). 使用@Before , @After , @AfterReturning , @AfterThrowing ,  @Around 将指定的方法设定为指定的通知类型
通用切入点的表示方式
1). 定义 : @Pointcut声明在无返回值方法上方
2). 使用 : @Around("类名.方法名()") , 如: @Around("MyAdvice3.pt1()")


注解AOP注意事项
1). 返回值接收 : @AfterReturning(value="MyAdvice3.pt1()",returning="obj")
2). 异常接收 : @AfterThrowing(value="MyAdvice3.pt1()",throwing="t")
3). 同一类, 不同通知类型间的顺序
around before
before
around after
after
afterReturning
4). 同一种通知类型 : 同一个通知类中,aop方法的执行顺序与方法名称有关系


团队开发(了解)
团队开发模式
导入配置文件 : <import resource=" ... "/>
加载多个配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-team.xml","applicationContext-team1.xml");
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] { "applicationContext-team.xml","applicationContext-team1.xml" }) 
bean的命名冲突
注意 : 配置了相同id的bean在不同的配置文件中, 后面的会覆盖前面的 ; 如果在同一个配置文件中定义了两个相同id的bean时, 将会报错

bean中的name属性 : 该属性可以定义多个 (多个之间使用 "," 或 空格进行分割), 用来获取bean, name属性主要服务于团队开发过程 ; <bean id="..." name="name1, name2" />