Spring中的AOP配置

Spring中的配置文件,一般情况下命名为applicationContext.xml,myeclipse会自动用spring编辑器进行编辑。


加载顺序:

1、首先读取配置配置文件,扫描所有的配置的bean对象,将其实例化。(因为懒加载的原因,某些情况下如果客户端没有getbean的话不会为该bean实例化)

2、然后读取aop切面配置,为目标类创建代理对象。

3、然后将所有注入信息的bean,属性,代理对象注入到对应的位置。


涉及的一些命名 空间的整理:

基于xml的方式的命名空间:随着使用功能的增多,命名空间也会越来越多,暂时只列出够基本使用的。以后慢慢补充

xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">


在<bean id="" class="">中配置要交由spring来管理的javabean。spring会在启动时自动创建该类的实例。

而在默认情况下,bean的模式是单例模式,在于struts2整合时不太合适,需要在bean中声明属性 将scope=“prototype”即可。

例:

         <bean id="testSalary" class="com.itheima.some.TestSalary" scope="prototype"></bean>

同其他的框架配置文件一样id必须是唯一的。不 能重复。

而在某些情况下如果配置了name属性,需要注意的是name属性是可以重复的,并且后加载的name会将之前name相同的覆盖掉。


在spring中如果要使用事务必须进行如下配置  <aop:config>标签。在该标签中需要:

           <aop:pointcut expression="execution(* com.itheima.some.*.*(..))"    id="perform"></aop:pointcut>

其中expression=execution是写死的,后面的括号中的内容是按照匹配正则表达式的要求来扫描需要创建的代理对象。

这里的匹配一定要书写正确否则报的错误很难排查。



关于spring中的几种通知:


前置通知:


1、在切面类中,没有必要实现接口,但方法名称要与<aop:before method=”checkSecurity” 中的checkSecurity一样。

2checkSecurity方法中通过JoinPoint参数可以获得目标类的目标方法名称、参数值等信息。可以用来判断调用的是哪个方法等。


例: <aop:aspect ref="logs">
            <aop:before method="startLogs" pointcut-ref="perform"></aop:before>
        </aop:aspect>


A. 后置通知

1、 没有特殊说明的地方和前置通知是一样的。

2、 在spring配置文件中

        

3、 在拦截器中的方法要和checkSecurity方法一样,有两个参数

              JoinPoint   point    可以获得目标方法和参数值

              Object      val    这里的名字要和returning=”val”中保持一致,指的是方法的返回值。

4、 returning=”val”时,通知里可以有返回参数,这个参数只能决定通知里能不能拿到方法的返回值,和客户端没有关系。

5、  在执行目标类的目标方法中遇到异常,则不执行后置通知。


B. 异常通知

1、 没有特殊说明的地方和前置通知一样

2、 在spring配置文件中

              

其中throwing指定了传递异常的参数名称

3、 在异常通知中(拦截器)中,必须是checkSecurity方法。方法中有两个参数

                JoinPoint    point   可以获得方法的名称、参数

               Throwable   ex    利用ex.getMessage()可以获得异常信息

C. 最终通知

1、 没有特殊说明,和前置通知的配置一样。

2、 在spring配置文件里:

                 

            

说明:在最终通知中不受异常的影响。也就是说不论目标方法执行的过程中是否抛出异常,最终通知都将执行。

D. 环绕通知

1、 没有特殊说明和前置通知的配置保持一致。

2、 在spring文件中


                

3、 在环绕通知中,方法名称为checkSecurity。参数 类型 为ProceedingJoinPoint。

ProceedingJoinPointproceed方法相当于invoke方法,调用目标类的目标方法。ProceedingJoinPoint继承了JoinPoint

4、  能在方法执行的前后加入额外的代码。例如进行权限的判断。


在spring中的配置例子:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
    <!--
        1、目标类
        2、切面
        3、进行AOP的配置
     -->
     <bean id="classDao" class="cn.itheima03.spring.aop.xml.ClassesDaoImpl"></bean>
     <bean id="myTransaction" class="cn.itheima03.spring.aop.xml.MyTransaction"></bean>
    
     <aop:config>
         <!--
             切入点表达式
                 expression切入点表达式
                 id  唯一标示
          -->
         <aop:pointcut expression="execution(* cn.itheima03.spring.aop.xml.ClassesDaoImpl.*(..))" id="perform"/>
         <!--
             ref引向切面
          -->
         <aop:aspect ref="myTransaction">
         
             <aop:before method="beginTransaction" pointcut-ref="perform"/>
         
             <!--
                 后置通知
                     returning 返回值
              -->
              <!--
             <aop:after-returning method="commit" pointcut-ref="perform" returning="val"/>
              -->
             <!--
                 最终通知
                        无论目标方法是否有异常,都执行
              -->
              <!--
             <aop:after method="finnalyMethod" pointcut-ref="perform"/>
              -->
             <!--
                 异常通知
                     throwing 获取目标方法抛出的异常信息
              -->
             <aop:after-throwing method="throwingMethod" pointcut-ref="perform" throwing="ex"/>
             <!--
             <aop:around method="aroundMethod" pointcut-ref="perform"/>
              -->
         </aop:aspect>
     </aop:config>
</beans>




其中:切入点表达式的匹配方式示例:

          execution(public * *(..))  所有的公共方法

          execution(* set*(..))  以set开头的任意方法

          execution(* com.xyz.service.AccountService.*(..))com.xyz.service.AccountService类里的所有的方法

          execution(* com.xyz.service.*.*(..)) com.xyz.service包下的所有类的所有的方法

          execution(* com.xyz.service..*.*(..)) com.xyz.service包及子包中所有的类的所有的方法

          execution(* cn.itheima03.spring..*.*(String,*,Integer))

          execution(* cn.itheima03.*.*.spring.*..*.*(..))  参数..代表任意类型的任意参数,参数可以是0个
   

          cn.itheima03.a.b.spring.c.d.A.a()



springAOP的原理:
   1、当启动spring容器的时候,
         <bean id="classDao" class="cn.itheima03.spring.aop.xml.ClassesDaoImpl"></bean>
         <bean id="myTransaction" class="cn.itheima03.spring.aop.xml.MyTransaction"></bean>
       把这两个bean创建对象了
   2、解析aop:config
        1、解析切入点表达式,把表达式解除出来以后和spring中的bean进行匹配
        2、如果匹配成功,则为该bean创建代理对象,在创建代理对象的过程中,把目标方法和通知结合在一起了
           如果匹配不成功,则直接报错
        3、当客户端调用context.getBean时,获取到的
                                          1、如果该对象有代理对象,则返回代理对象
                                          2、如果该对象没有代理对象,则返回对象本身


说明:
   spring容器内部会自动判断:
              如果目标类实现了接口,则采用jdkproxy
              如果目标类没有实现接口,则采用cglibproxy

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章