javascript
这波 springframework5.x 我先干了(aop编程) -凯发ag旗舰厅登录网址下载
一、静态代理设计模式
1.为什么需要代理设计模式
1.1问题
-
在javaee分层开发过程中,哪个层次对于我们来讲最重要
dao—>service–>controller
javaee分层开发中,最为重要的是service service业务层 -
service层中包含了哪些代码?
service层中 =核心功能代码(几十行 上百行) 额外功能代码(附加功能)1.核心功能业务运算dao调用2.额外功能不属于业务可有可无代码量小例如:事务、日志、性能。。。 -
额外功能书写在service层中好不好?
service层的调用者(controller):需要在service层书写额外功能软件设计者:service层不需要额外功能 -
现实生活中 的解决方式
2.代理设计模式
2.1概念通过代理类,为原始类(目标)增加额外功能
好处:利于原始类(目标)的维护2.2名词解释
1.目标类 原始类指的是 业务类(核心功能 --->业务运算 dao调用)2.目标方法 原始方法目标类(原始类)中的方法 就是目标方法(原始方法)3.额外功能(附加功能) 日志,事务,性能2.3代理开发的核心要素
代理类=目标类(原始类)额外功能原始类(目标类)实现相同的接口 房东---->public interface userservice{m1(){}m2(){}}userserviceimpl implements userservice{m1(){}m2(){}}2.4编码
静态代理: 为每一个原始类,手工编写一个代理类(.java .class)
2.5静态代理存在的问题
1.静态类文件过多,不利于项目管理userserviceimpl userserviceproxyorderserviceimpl orderserviceproxy2.额外功能维护性差代理类中 额外功能修改复杂(麻烦)
二、spring的动态代理开发
1.spring动态代理的概念
概念:通过代理类为原始类(目标类)增加额外功能
好处:利于原始类(目标类)的维护
2.搭建开发环境
<dependency><groupid>org.springframeworkgroupid><artifactid>spring-aopartifactid><version>5.1.14.releaseversion>dependency><dependency><groupid>org.aspectjgroupid><artifactid>aspectjrtartifactid><version>1.8.8version>dependency><dependency><groupid>org.aspectjgroupid><artifactid>aspectjweaverartifactid><version>1.8.3version>dependency>3.spring动态代理的开发步骤
①创建原始对目标对象
②、额外功能
methodbeforeadvice接口
额外的功能书写在接口的实现中,运行在原始方法之前运行额外功能
public class before implements methodbeforeadvice {/*作用:需要把运行在原始方法执行之前运行的额外功能,书写在before方法中*/@overridepublic void before(method method, object[] objects, object o) throws throwable {system.out.println("======额外功能=====");} } <bean id="before" class="com.myspring.dynamic.before" />③、定义切入点
切入点:额外功能加入的位置目的:由程序员根据自己的需要,决定额外功能加入给哪个原始方法 registe / longin 简单的测试:所有方法都作为切入点都加入额外的功能。 <aop:config><aop:pointcut id="pc" expression="execution(* *(..))"/>aop:config>④、组装(②、③整合)
表达的含义:所有方法 都加入before的额外功能<aop:advisor advice-ref="before" pointcut-ref="pc"/> 这是④的完整配置<aop:config><aop:pointcut id="pc" expression="execution(* *(..))"/><aop:advisor advice-ref="before" pointcut-ref="pc"/>aop:config>⑤、调用
目的:获得sporing工厂的动态代理对象,并进行调用applicationcontext applicationcontext = new classpathxmlapplicationcontext("/applicationcontext.xml");注意:1.spring的工厂通过原始对象的id值获得的是代理对象2.获得代理对象后,可以通过声明接口类型,进行对象的存储userservice userservice = applicationcontext.getbean("userservice", userservice.class);userservice.login("bugz","123456");userservice.register(new user("bugz","123456"));4.动态代理细节分析
①、spring创建的动态代理类在那里?
spring框架在运行时,通过动态字节码技术,在jvm创建的,运行在jvm内部,等程序结束后,会和jvm一起消失。
————————————————————————————————————————————————————
什么叫动态字节码技术:通过第三方动态字节码框架,在jvm中创建对应类的字节码,进而创建对象,当虚拟机结束,动态字节码跟着消失。
—————————————————————————————————————————————————
结论:动态代理不需要定义类文件,都是jvm运行过程中动态创建的,所以不会造成静态代理,类文件数量过多,影响项目管理的问题。
②、动态代理编程简化代理的开发
在额外功能不变的前提下,创建其他目标类(原始类)的代理对象时,只需要指定原始(目标)对象即可。
③动态代理额外功能的维护性大大增强
三、spring动态代理详解
1.额外功能的详解
- methodbeforeadvice分析
- methodinterceptor(方法拦截器)
额外功能运行在原始代码方法执行之后
@overridepublic object invoke(methodinvocation methodinvocation) throws throwable {object proceed = methodinvocation.proceed();system.out.println(" 额外功能运行在之后 ");return proceed;}额外功能运行在原始代码方法执行之前、之后。
什么样的额外功能,运行在原始方法之前,之后都要添加? 例:事务@overridepublic object invoke(methodinvocation methodinvocation) throws throwable {system.out.println(" 额外功能运行在之前 ");object proceed = methodinvocation.proceed();system.out.println(" 额外功能运行在之后 ");return proceed;}额外功能运行在原始方法抛出异常的时候
@overridepublic object invoke(methodinvocation methodinvocation) throws throwable {object proceed = null;try {proceed = methodinvocation.proceed();} catch (throwable throwable) {system.out.println(" 抛出异常时的 额外功能 ");throwable.printstacktrace();}return proceed;}methodinterceptor影响原始方法的返回值
原始方法的返回值,直接作为invoke方法的返回值返回,methodinterceptor不会影响原始方法的返回值 methodinterceptor影响原始方法的返回值 invoke方法的返回值,不要直接返回原始方法的运行结果即可。@overridepublic object invoke(methodinvocation methodinvocation) throws throwable {system.out.println(" 额外功能 ");object proceed = methodinvocation.proceed();return false;}2.切入点详解
切入点决定额外功能加入位置(方法) <aop:pointcut id="pc" expression="execution(* *(..))"/> execution(* *(..)) --->匹配了所有方法 a b c1.execution() 切入点函数 2.* *(..) 切入点表达式2.1切入点表达式
①、方法切入点表达式
- 定义login方法的切入点* login(..) #定义register作为切入点 * register(..)
- 定义long方法且login方法有两个字符串类型的参数 作为切入点* login(string,string) #注意:非java.lang包中的类型,必须要写全限定名 * register(com.xxx.xxx.user) # ..可以和具体的参数类型连用 * login(string,..) -> login(string)/login(string,string)/login(string,com.xxx.user)
- 精准方法切入点限定修饰符 返回值 包.类.方法(参数) * com.xxx.xxx.login() * com.xxx.xxx.login(string,string)
②、类切入点
指定特定类作为切入点(额外功能加入的位置),自然这个类中的所有方法,都会加上额外的功能
- 语法1#类中所有的方法加入了额外功能 * com.xx.xx.userserviceimpl.*(..)
- 语法2 #忽略包1.类只存在一级包 com.userserviceimpl* *.userserviceimpl.*(..)2.类存在多级包 com.xxx.xxx.xxx.userserviceimpl* *..userserviceimpl.*(..)
③、包切入点 实战
指定包作为额外功能加入的位置,自然包中所有类及其方法都会加入额外功能
-
语法1
#切入包中的所有类,必须在xxx中,不能在xxx包的子包中 * com.a.xxx.*.*(..) -
语法2
#切入点当前包及其子包都生效 * com.a.xxx..*.*(..)
2.2切入点函数
切入点函数:用于执行切入点表达式
①、execution
最为重要的切入点函数,功能最全 执行 方法切入点表达式 类切入点表达式 包切入点表达式弊端:execution执行切入点表达式,书写麻烦execution(* com.xxx.xxx..*.*(..)) 注意: 其他的切入点函数 简化execution书写复杂度,功能上完全一致②、args
作用:主要用于函数(方法)参数的匹配 切入点:例如---方法参数必须得是2个字符串类型的参数execution(* *(string,string))args(string,string)③、within
作用:主要用于进行类、包切入点表达式的匹配 切入点:userserviceimpl这个类execution(* *..userserviceimpl.*(..))within(*..userserviceimpl)execution(* com.xx.xx..*.*(..))within(com.xx.xx..*)④、@annotation
作用:为具有特殊注解的方法加入额外功能 <aop:pointcut id="pc" expression="@annotation(com.xx.log)"/>⑤、切入点函数的逻辑运算
指的是整合多个切入点函数一起配合工作,进而完成更为复杂的需求
- and与操作
- or或操作
四、aop编程
1.aop编程
aop(aspect oriented programming) 面向切面编程 = spring动态代理开发
以切面为基本单位的程序开发,通过切面间的彼此协同,相互调用,完成程序的构建
切面 = 切入点 额外功能
oop(object oriented programming) 面向对象编程 java
以对象为基本单位的程序开发,通过对象间的彼此协同,相互调用,完成程序的构建
pop(procedure oriented programming) 面向过程(方法、函数)编程 c语言
以过程为单位的程序开发,通过过程间的彼此协同,相互调用,完成程序的构建。
aop的概念:本质就是spring的动态代理开发,通过代理类为原始类增加额外功能。
好处:利于原始类的维护
注意:aop编程不可能取代oop,oop编程有意补充。
2.aop编程的开发步骤
1.原始对象
2.额外功能(methodinterceptor)
3.切入点
4.组装切面(额外功能 切入点)
3.切面的名词解释
切面 = 切入点 额外功能
几何学:面=点 相同性质
五、aop底层实现原理
1.核心问题
1.aop如何创建动态代理类(动态字节码技术) 2.spring工厂如何加工创建代理类对象通过原始类对象的id值,获得的是代理对象2.动态代理类的创建
2.1、jdk的动态代理
- proxy.newproxyinstance方法参数详解
- 编码
2.2 cglib动态代理
cglib创建动态代理的原理:父子继承关系创建代理对象,原始类作为父类,代理类作为子类,这样既可以保证二者方法一致,同时在代理类中提供新的实现(额外功能 原始方法)
- 编码
- 总结
1.jdk动态代理 proxy.newproxyinstance() ------------通过接口创建代理的实现类
2.cglib动态代理 enhancer---------------------------------通过继承父类创建代理类
3.spring工厂如何加工原始对象
- 思路分析
- 编码
六、基于注解的aop编程
1.基于注解的aop开发步骤
1.原始对象
2.额外功能
3.切入点
4.组装切面
2.切入点复用
(1)切入点复用
(2)、动态代理的创建方式
aop底层实现 2种代理创建方式 1.jdk 通过实现接口 做新的实现类方式 创建代理对象 2.cglib 通过继承父类 做新的子类 创建代理对象默认情况 aop编程底层应用jdk动态代理创建方式 如果切换cglib1.基于注解aop开发七、aop开发中的一个坑
坑:在同一个业务类中,进行业务方法间的相互调用,只有最外层的方法,才是加入了额外功能(内部的方法,通过普通的方式调用,都调用的是原始方法)。如果想让内层的方法也调用代理对象的方法,就要applicationcontextaware获得工厂,进而获得代理对象。 public class userserviceimpl implements userservice, applicationcontextaware {private applicationcontext ctx;@overridepublic void setapplicationcontext(applicationcontext applicationcontext) throws beansexception {this.ctx = applicationcontext;}@overridepublic void register(user user) {system.out.println("userserviceimpl.register");/*调用的是原始方法的login方法--->核心功能设计的目的:代理对象的log方法 ——————>额外功能 核心功能applicationcontext classpathxmlapplicationcontext = new classpathxmlapplicationcontext("/applicationcontext2.xml");userservice userservice =(userservice) classpathxmlapplicationcontext.getbean("userservice");userservice.login();spring工厂重量级资源 一个应用中 应该只创建一个工厂*/userservice userservice = (userservice) ctx.getbean("userservice");userservice.login("bugz", "123444");}@overridepublic void login(string name, string password) {system.out.println("userserviceimpl.login");} }八、aop阶段知识总结
总结
以上是凯发ag旗舰厅登录网址下载为你收集整理的这波 springframework5.x 我先干了(aop编程)的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得凯发ag旗舰厅登录网址下载网站内容还不错,欢迎将凯发ag旗舰厅登录网址下载推荐给好友。
- 上一篇:
- 下一篇: