Spring框架---AOP

Spring--AOP思想

上节我们解释了Spring的IOC,其实简单的说IOC是干什么的呢?

IOC和DI就是为一些类中作为对象的属性、集合、属性文件以及一般类型的变量赋值,即注入。

当然只是注入的方式不同例如由setter注入,构造输入,还有就是注解开发;

再本篇中将为大家说明,Spring的第二个核心AOP(面向切面编程)。

首先,什么是面向切面编程?大家应该都学过OOP(面向对象编程),相较于OOP来说,AOP采用的机制就是采取横向抽取的机制来取代传统的纵向继承,举个例子:

举个简单的例子,对于“雇员”这样一个业务实体进行封装,自然是OOP/OOD的任务,我们可以为其建立一个“Employee”类,并将“雇员”相关的属性和行为封装其中。而用AOP设计思想对“雇员”进行封装将无从谈起。

   同样,对于“权限检查”这一动作片断进行划分,则是AOP的目标领域。而通过OOD/OOP对一个动作进行封装,则有点不伦不类。

换而言之,OOD/OOP面向名词领域,AOP面向动词领域。

一  AOP术语

要想面向切面编程,我们首先得了解一些基本的术语以及几种不同的通知:

1.target目标类:需要被代理的类,我们可以简单的理解为需要服务层中需要公共模块能力的类;

2.JoinPoint连接点:可能被拦截的方法(服务层中所有的方法);

3.CutPoint切入点:需要被增强的方法,也即需要公共能力(事务)的方法,当然查找时不需要的;

4.Advice:通知:它指的就是公共模块的能力;

5.Weaving织入:它是一个虚拟的概念,把通知应用到目标类中创建代理的过程就叫做织入;

6.Proxy代理类:由Spring提供的代理类来完成通知和切入点的整合

7.Aspect切面:连接点和Advice的结合,比如说将日志这种能力加如到tel()这个方法中,就形成一个切面,当你每次调用这个方法的时候,也同时回执行这个dan
注意:Aop用到的地方就是项目的服务层,其实IOC与DI就是用来给服务层中的一些属性复制的;

再上面的七个名词当中Advice有有三中不同的类型:
1.前置通知 MethodBeforeAdvice

2.后置通知:afterreturnAdvice

3.环绕通知:around

 

接下来将从手动模式,AOP全自动模式,AspectJ模式的开发;

 

1手动模式

  开发步骤分为三大步和三小步

1) 开发通知类

创建类实现MethodBeforeAdvice—构建前置的通知类

创建类实现aftertrRturnAdvice—构建后置的通知类

创建类实现MethodInterceptor—构建环绕的通知类

再具体的场景种一般只使用一种通知;

2) 再服务层创建接口及其实现类

我们一般会在服务层做一些逻辑的判断

再此时我们开发的公共能力通知类和目标类之间是独立的,所以我们应该创建代理类来将二者整合。

  3)配置代理类

<!-- 创建通知类对象-->
   <bean id="wwww" class="通知类的路径"></bean>
   <!--  创建目标类对象-->
<bean id="AdviceService" class="目标类的包名+实现类类名"></bean> 
   <!-- 配置代理对象-->
   <bean id="Proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- ProxyFactoryBean工厂类在此处返回的不是自己的对象,而是通过其内部的getObject方法得到对应的代理类的对像-->
       <!-- 整合目标类-->
       <!--<propertyname="target" ref="目标类的id wwww"></property>-->
       <!-- 整合通知类-->
       <property name="interceptorNames">
        <!-- interceptorNames的原由就是其内部参数是可变参数,可以整合多个通知-->
           <list>
               <value>AfterAdvice</value>
           </list>
       </property>
       <!-- 关联接口-->
       <property name="proxyInterfaces">
           <!-- proxyInterfaces其内部参数是一个数组,这样就可以关联多个接口-->
           <array>
               <value>com.qf.service.UserService</value>
               <value>com.qf.service.AdviceService</value>
           </array>
       </property>
   </bean>

2 AOP全自动模式

此方法和之前的方法三大步相同,只不过不需要三小步了,而是直接开启AOP全自动编程

具体的配置如下:

<!-- 创建通知类对象-->
   <bean id="AfterAdvice" class="通知类的路径"></bean>
   <!-- 创建目标类对象-->
   <bean id="UserService" class="目标类的包名+实现类类名"></bean>

<aop:config>
    <!--  切入点:找到目标类中的方法:切入点表达式 -->
    <aop:pointcut id="cut" expression="execution(*com.ww.service.*.*(..))"></aop:pointcut>
    <!-- 让通知和切入点关联 -->
    <aop:advisor advice-ref="AfterAdvice"pointcut-ref="cut"></aop:advisor>
</aop:config>

二者的不同之处就在于后者再得到对象时直接使用的目标类对象的id而对于第一个来说使用的时代理类的id即之前的 Proxy。

在这里解释一下切入表达式:

语法:execution(权限修饰符 返回值类型  包名.类名.方法名.(参数))

execution(* com.ww.service.*.*(..))此为一般格式,当然也不乏有些公司按照模块来划分,只需要稍稍变得即可。

3 AspectJ模式的开发

AspectJ的通知类型:@before@afterreturning  @around

AspectJ编写的特点:

     不需要实现接口

     方法名称随意

     通过参数来引入切入点

1)编写公共功能通知类

一般前置的参数为 (JoinPoint  joinpoint)括号内几位参数下面相同;

后置的参数为 (JoinPoint  joinpoint,Object res)

后置的返回参数是可以返回的;

也就是说,当调用有返回值的参数的时候,函数的返回时会到res当中,可以随着通知输出;

环绕的参数为 (ProceedingJoinPoint  joinpoint)

但是环绕同时需要手动来调用方法

   参数.proceeding();

2)服务层接口及其实现类的编写

1) AOP全自动编程

让通知和切入点关联形成切面;

<bean id="MyAdvice" class="通知类所在包"></bean>
   <bean id="UserService" class="目标类的包名+实现类类名"></bean>
    <aop:config>(AOP特有的节点)

(关联自定义对象)
        <aop:aspect ref="MyAdvice">

(切入点表达式)
   <aop:pointcut id="mypoint"expression="execution(*com.ww.service.*.*(..))">

</aop:pointcut>
     aop:after-returning method="
具体通知类种的方法名" pointcut-ref="切入点表达式的id" returning="res">此处返回值应该与之前方法种的返回值名称相同

</aop:after-returning>
       </aop:aspect>

 </aop:config>

下一篇将会就注解方式的开发做说明,敬请期待!
版权声明:本文为博主原创文章,未经博主允许不得转载。

猜你喜欢

转载自blog.csdn.net/qq_42112846/article/details/80834436