欢迎访问 生活随笔!

凯发k8官方网

当前位置: 凯发k8官方网 > 前端技术 > javascript >内容正文

javascript

这波 springframework5.x 我先干了(aop编程) -凯发k8官方网

发布时间:2024/1/18 javascript 43 豆豆
凯发k8官方网 收集整理的这篇文章主要介绍了 这波 springframework5.x 我先干了(aop编程) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

一、静态代理设计模式

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动态代理的开发步骤
①创建原始对目标对象

public class userserviceimpl implements userservice {@overridepublic void register(user user) {system.out.println("userserviceimpl.register===核心业务代码注册 调用dao");}@overridepublic boolean login(string name, string password) {system.out.println("userserviceimpl.login======核心业务代码登录 调用dao");return false;} } <bean id="userservice" class="com.myspring.proxy.userserviceimpl" />

②、额外功能
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分析
1.methodbeforeadvice接口作用:额外功能运行在原始方法之前,进行额外功能操作。public class before implements methodbeforeadvice {/*作用:需要把运行在原始方法执行之前运行的额外功能,书写在before方法中方法参数介绍:method method: 额外功能所增加给的那个原始方法object[] objects: 额外功能所增加给的那个原始方法的参数。object o:额外功能所增加给的那个原始对象*/@overridepublic void before(method method, object[] objects, object o) throws throwable {system.out.println("======额外功能=====");} } ——————————————————————————————————————————————————————————————————————————————————————2.before方法中的三个参数在实战中该如何使用before方法中的参数,在实战中,会根据需要进行使用,不一定都会用到,也有可能都不用。
  • methodinterceptor(方法拦截器)
methodinterceptor接口:额外功能可以根据需要运行在原始方法执行 前、后、前后。-------------------------------------------------------------------public class around implements methodinterceptor {/*invoke方法的作用:额外功能书写在invoke额外功能可以加在 原始方法之前原始方法之后原始方法之前and之后确定:原始方法怎么执行methodeinvocation.proceed();参数:methodinvocation methodinvocation:额外功能所增加给的那个原始方法返回值:原始方法的返回值*/@overridepublic object invoke(methodinvocation methodinvocation) throws throwable {system.out.println(" 额外功能运行在之前 ");object proceed = methodinvocation.proceed();return proceed;}}

额外功能运行在原始代码方法执行之后

@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与操作
案例:login 同时 参数2个字符串1.exection(* login(string,string))2.exection(* login(.)) and args(string,string)注意 与操作不同用于同种类型的切入点函数案例:register方法和login方法作为切入点exection(* login(..)) or execution(* register(..))
  • or或操作
案例:register方法和login方法作为切入点exection(* login(..)) or execution(* register(..))

四、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方法参数详解


  • 编码
public class testjdkproxy {public static void main(string[] args) {//1.创建原始对象userserviceimpl userservice = new userserviceimpl();invocationhandler invocationhandler = new invocationhandler() {@overridepublic object invoke(object proxy, method method, object[] args) throws throwable {system.out.println("====log====");//原始方法运行object invoke = method.invoke(userservice, args);return invoke;}};//2.jdk创建动态代理userservice userservice1 =(userservice) proxy.newproxyinstance(userservice.class.getclassloader(),userservice.getclass().getinterfaces(),invocationhandler);userservice1.login("bugz","123");userservice1.register(new user("bugz","123"));/*细节问题:1.借用类加载器 userservice/testjdkproxy2.jdk8.x前 需要这样写 final userserviceimpl userservice = new userserviceimpl();*/}

2.2 cglib动态代理

cglib创建动态代理的原理:父子继承关系创建代理对象,原始类作为父类,代理类作为子类,这样既可以保证二者方法一致,同时在代理类中提供新的实现(额外功能 原始方法)

  • 编码
import com.myspring.proxy.user; import org.springframework.cglib.proxy.enhancer; import org.springframework.cglib.proxy.methodinterceptor; import org.springframework.cglib.proxy.methodproxy;import java.lang.reflect.method;public class testcglib {public static void main(string[] args) {//1.创建原始对象userservice userservice = new userservice();/*2.通过cglib的方式创建动态代理对象jdk创建代理方式 proxy.newproxyinstance(classloader,interfaces,invocationhandler)enhancer.setclassloader();enhancer.setsuperclass();enhancer.setcallback();---->methodinterceptor(cglib)enhancer.create()--->代理*/enhancer enhancer = new enhancer();enhancer.setclassloader(testcglib.class.getclassloader());enhancer.setsuperclass(userservice.getclass());methodinterceptor methodinterceptor = new methodinterceptor() {@overridepublic object intercept(object o, method method, object[] args, methodproxy methodproxy) throws throwable {system.out.println("------cglib new log--------");object invoke = method.invoke(userservice, args);return invoke;}};enhancer.setcallback(methodinterceptor);userservice userserviceproxy=(userservice) enhancer.create();userserviceproxy.login("bugz","123456");userserviceproxy.register(new user());} }
  • 总结

1.jdk动态代理 proxy.newproxyinstance() ------------通过接口创建代理的实现类
2.cglib动态代理 enhancer---------------------------------通过继承父类创建代理类

3.spring工厂如何加工原始对象

  • 思路分析
  • 编码
import org.springframework.beans.beansexception; import org.springframework.beans.factory.config.beanpostprocessor; import java.lang.reflect.invocationhandler; import java.lang.reflect.method; import java.lang.reflect.proxy;public class proxybeanpostprocessor implements beanpostprocessor {@overridepublic object postprocessbeforeinitialization(object bean, string beanname) throws beansexception {return null;}//使用jdk代理模拟工厂的代理@overridepublic object postprocessafterinitialization(object bean, string beanname) throws beansexception {invocationhandler invocationhandler = new invocationhandler() {@overridepublic object invoke(object proxy, method method, object[] args) throws throwable {system.out.println("---模拟代理的额外功能---");system.out.println(beanname);object invoke = method.invoke(bean, args);return invoke;}};return proxy.newproxyinstance(proxybeanpostprocessor.class.getclassloader(),bean.getclass().getinterfaces(),invocationhandler);} } <bean id="userservice" class="com.myspring.factory.userserviceimpl"/><bean id="beanpostprocessor" class="com.myspring.factory.proxybeanpostprocessor"/>

六、基于注解的aop编程

1.基于注解的aop开发步骤
1.原始对象
2.额外功能
3.切入点
4.组装切面

#通过切面类 定义了 额外功能@around定义了切入点@around("execution(* login(..))")@aspect 切面类/*1.额外功能public class myaround implements methodinterceptor{public object invoke(methodinvocation invocation){object ret = invocation.proceed();return ret;}}2.切入点*/ @aspect public class myaspect {@around("execution(* login(..))")public object around(proceedingjoinpoint joinpoint) throws throwable {system.out.println("---切面类额外功能");object proceed = joinpoint.proceed();return proceed;} } <bean id="userservice" class="com.myspring.aspectproxy.userserviceimpl"/><bean id="arround" class="com.myspring.aspectproxy.myaspect"/><aop:aspectj-autoproxy/>

2.切入点复用
(1)切入点复用

#切入点复用:在切面类中定义一个函数 上面加@pointcut注解 通过这种方式,定义切入点表达式,后续更加有利于切入点复用。 @aspect public class myaspect { @pointcut("execution(* login(..))")public void pointcut(){}@around(value = "pointcut()")public object around(proceedingjoinpoint joinpoint) throws throwable {system.out.println("---切面类额外功能111");object proceed = joinpoint.proceed();return proceed;}@around(value = "pointcut()")public object around2(proceedingjoinpoint joinpoint) throws throwable {system.out.println("---切面类额外功能222");object proceed = joinpoint.proceed();return proceed;} }

(2)、动态代理的创建方式

aop底层实现 2种代理创建方式 1.jdk 通过实现接口 做新的实现类方式 创建代理对象 2.cglib 通过继承父类 做新的子类 创建代理对象默认情况 aop编程底层应用jdk动态代理创建方式 如果切换cglib1.基于注解aop开发2.传统的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阶段知识总结

总结

以上是凯发k8官方网为你收集整理的这波 springframework5.x 我先干了(aop编程)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得凯发k8官方网网站内容还不错,欢迎将凯发k8官方网推荐给好友。

  • 上一篇:
  • 下一篇:
网站地图