首页 > 代码库 > Spring_day03
Spring_day03
代理模式:
客户:租一间好的房子(便宜的)
MIS(代理人):找房子,看房子,租房子,交中介费
房东:房东出租房屋。
代理模式的特征:
1.代理者(Proxy)必须实现和被代理者(房东)相同的接口(这样看起来才能和被代理者一模一样)
2.在完成客户要求以后,还要做其他的操作(收取中介费)
2.静态代理模式(一种思想)
2.1说明:
事务模块是系统开发过程中必不可少的模块。会有专门的团队或负责人来负责。可是一旦事务模块和业务模块交织在一起,就会造成代码的紧耦合。
理想模式:
事务模块的代码只处理事务的方法,而业务模块代码只处理业务,
两者之间最好不要有直接的联系。否则代码的耦合性较高,后期不易于维护和扩展。
2.1使用静态代理模式解决紧耦合的问题
通过静态代理模式:可以实现业务和事务方法相分离。解决了二者之间的耦合性问题。
问题:虽然能够解决耦合性问题。但是重复代理量较多。每写一个方法都必须添加事务的相关代码。实质上就是代码的迁移,没有做到代码的重用和灵活。代理对象只能代理一个接口。
3.动态代理模式
JDK的动态代理
被代理者必须实现接口,如果没有实现接口那么JDK就不能生成代理对象。生成代理对象的速度较快
Cglib的动态代理
1.被代理者有无接口都能生成代理对象。
2.生成的代理对象都是被代理者的子类。
3.内部生通过二进制码来帮助生成代理对象,所有对象的生成速度很慢。但是一旦生成了代理对象。执行速度很快。
4.JDK的动态代理
能够生成代理对象 其class形式
class com.sun.proxy.$Proxy6
5.Cglib的动态代理
//增强器
Enhancer enhancer = new Enhancer();
//传入接口
enhancer.setInterfaces(target.getClass().getInterfaces());
//设置父类 必须
enhancer.setSuperclass(target.getClass());
//设置回调
enhancer.setCallback(new MethodInterceptor()
CGlib对象的类型
class service.PersonServiceImpl$$EnhancerByCGLIB$$ea3089c1
Spring内部集成了Cglib
6.SpringAOP
面向切面编程 一种思想
6.1名词解释
1.切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象。
一个切面就是在完成目标方法后再执行其操作的程序代码
2.连接点(Joinpoint):在程序执行过程中某个特定的点
就是客户端调用的目标方法。
3.通知(Advice):在切面的某个特定的连接点上执行的动作。
就是切面中的方法。
4.切入点(Pointcut):匹配连接点的断言
切入点就是一个匹配切面的过程
5.目标对象(Target Object): 被一个或者多个切面所通知的对象。
就是真正执行目标方法的对象
6.织入(Weaving):把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。
形成切面的过程就是织入。
6.2AOP的入门
步骤:
1.配置头文件 导入约束
xmlns:aop="http://www.springframework.org/schema/aop"
2.导入相关的开发jar包5个
3.配置自定义的切面
4.xml配置的顺序
Content Model : (pointcut*, advisor*, aspect*)
<aop:config>
<!--配置切入点 -->
<aop:pointcut expression="within(service.*)" id="pc"/>
<aop:aspect ref="myAspect">
<!--配置通知的方法 -->
<aop:around method="around" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
6.3:AOP的原理
当创建对象的时候首先spring和和切入点表达式进行匹配。如果匹配成功。则创建代理对象。我们客户端拿到代理对象后看上去和目标对象一模一样。//????
调用目标对象执行方法。就会执行切面中的通知(方法)。利用代理对象完成一些额外的操作。最终执行目标方法。
6.4:通知的类型
1.环绕通知(Around Advice):在目标方法执行之前。执行之后都需要执行额外操作的通知。
2.前置通知(Before advice):在目标方法执行之前的操作。
3.后置通知(After returning advice):在目标方法执行之后执行的通知
4.异常通知(After throwing advice):在执行目标方法时,如果目标方法报错就会被异常通知拦截,这时异常通知才会执行。
5.最终通知(After (finally) advice):不管如何都会执行最终通知。
6.5 异常的处理
在Spring中异常的try--catch不能随便加,如果添加了try-catch那么spring容器就捕获不到。不能做出正确的处理。如果想写try-catch那么异常捕获时要具体指明某一类的异常 不能使用Exception,因为这个异常捕获能力太强。
6.6通知的处理顺序
当目标方法执行抛出异常时 异常通知会被执行,后置通知不会被调用。
6.7通知的使用场景
1.环绕通知:我是不需要目标方法执行,并且执行前后有必要的操作。
2.前置通知:日志收集????? 前置通知执行不能影响目标方法是否被执行 与它毫无关系。
3.后置通知:如果需要对目标方法的返回值结果做操作 可以使用后置通知。通知也不能影响目标方法的执行。
4.异常通知:可以对异常做收集 以后使用异常通知。
5.最终通知:可以用来关闭一些链接或者释放资源。
6.8通知中的参数
除了环绕通知之外其他的通知都是JoinPoint。并且所有的参数都必须位于第一位。
而环绕通知中 必须添加ProceedingJoinPoint 因为 只有ProceedingJoinPoint类中有proceed方法。才能让目标方法执行。
6.9关于表达式的写法
within(service.*)
它是一个类级别的表达式,可以按照类型来匹配。匹配的规则包名+类名。
如果想匹配该包下的所有子类 用*代替。 如果想匹配该包下的所有子孙类用
..*表示。
execution(返回值结果 包名.类名.方法名(参数名))
execution(* service..*(..))
表达式创建代理对象的原理;
只有满足表达式要求的才会被创建代理对象,能够精确到方法和参数级别。
Spring_day03