春(6)AOP

AOP:フルネームはアスペクト指向プログラミングです。つまり、アスペクト指向プログラミングです。

簡単に言えば、プログラムの反復コードを抽出することであり、実行する必要がある場合は、動的プロキシテクノロジーを使用して、ソースコードを変更せずに既存のメソッドを拡張します。

SpringでAOPを使用して動的プロキシを実装し、コードを簡素化する方法

ステップ1:ファイルのインポート座標

  <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
  </dependency>
   <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.7</version>
        </dependency>
 

ここでのaspectjweaverは、次のエントリポイント式を準備します

ステップ2:関連するbean.xmlを構成します

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">


<!--配置Service,Service中需要用到Dao-->
    <bean id="IUserService" class="com.imis.service.impl.UserServiceImpl">
        <property name="iUserDao" ref="IUserDao"></property>
    </bean>
<!--配置Dao,Dao中又继承BaseDao,BaseDao中需要用到QueryRunner-->
    <bean id="IUserDao" class="com.imis.dao.impl.UserDaoImpl">
        <property name="queryRunner" ref="runner"></property>
    </bean>

<!--    <context:component-scan base-package="com.imis"></context:component-scan>-->
<!--QueryRunner配置,注入数据源,由于QueryRunner中没有关于数据源的set方法,但提供了构造函数,所以用构造函数的方法来注入-->
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <constructor-arg name="ds" ref="dataSource"></constructor-arg>
    </bean>

<!--  配置数据源  -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/firstmybatis?serverTimezone=Asia/Shanghai"/>
        <property name="user" value="root"/>
        <property name="password" value="zhengyunyu524"/>
    </bean>
<!--  把log放进ioc容器中  -->
    <bean id="logger" class="com.imis.log.Log">

    </bean>
<!--配置aop-->
    <aop:config>
<!--    配置切面指定类    -->
        <aop:aspect id="logAdvice" ref="logger">
<!--      配置切面指定类的方法及要切入的类的方法      -->
<!--       前置     -->
            <aop:before method="before" pointcut="execution(public * com.imis.service.impl.UserServiceImpl.queryAll())"></aop:before>
<!--        后置    -->
            <aop:after-returning method="after" pointcut="execution(public * com.imis.service.impl.UserServiceImpl.queryAll())"></aop:after-returning>
<!--         异常   -->
            <aop:after-throwing method="afterexception" pointcut="execution(public * com.imis.service.impl.UserServiceImpl.queryAll())"></aop:after-throwing>
<!--         最终   -->
            <aop:after method="end" pointcut="execution(public * com.imis.service.impl.UserServiceImpl.queryAll())"></aop:after>

        </aop:aspect>
    </aop:config>
</beans>

SpringでのXMLベースのAOP構成手順
1.管理する
Springに通知Beanを提供します2.aop:configタグを
使用してAOP構成の開始を示します3. aop:アスペクトタグを使用して構成アスペクト
ID属性を示します:itアスペクト識別
ref属性に固有のアスペクトを提供します。指定された通知クラスBeanのIDです。
4. aop:アスペクトラベル内の対応するラベルを使用して、通知のタイプを構成します

        aop:before:表示配置前置通知
        aop:after-returning:后置通知
        aop:after-throwing:异常通知
        aop:after:最终通知
        method属性:用于指定Logger类中哪个方法是前置通知

ポイントカット属性:ポイントカット式を指定するために使用されます。式の意味は、ビジネス層のどのメソッドが拡張されるかを示します。

    切入点表达式的写法:
       关键字:execution(表达式)
       表达式:访问修饰符  返回值  包名.包名.包名...类名.方法名(参数列表)
       标准的表达式写法:
       public void com.itheima.service.impl.AccountServiceImpl.saveAccount()

サンプルログコード:

public class Log {
    
    

    public void before(){
    
    
        System.out.println("执行前");
    }
    public void after(){
    
    
        System.out.println("执行后");
    }
    public void afterexception(){
    
    
        System.out.println("有异常");
    }
    public void end(){
    
    
        System.out.println("最终结束");
    }
}

この時点で、AOPの構成に基づいてqueryAllメソッドを実行すると、次の結果が得られます。

执行前
[User{
    
    username='zzy', userid=1}, User{
    
    username='yxx', userid=2}, User{
    
    username='ss', userid=3}]
执行后
最终结束

エントリポイント式の書き方:

关键字:execution(表达式)
表达式:
    访问修饰符  返回值  包名.包名.包名...类名.方法名(参数列表)
标准的表达式写法:
     public void com.itheima.service.impl.AccountServiceImpl.saveAccount()
访问修饰符可以省略
    void com.itheima.service.impl.AccountServiceImpl.saveAccount()
返回值可以使用通配符,表示任意返回值
    * com.itheima.service.impl.AccountServiceImpl.saveAccount()
包名可以使用通配符,表示任意包。但是有几级包,就需要写几个*.
    * *.*.*.*.AccountServiceImpl.saveAccount())
包名可以使用..表示当前包及其子包
    * *..AccountServiceImpl.saveAccount()
类名和方法名都可以使用*来实现通配
     * *..*.*()
参数列表:
    可以直接写数据类型:
        基本类型直接写名称           int
        引用类型写包名.类名的方式   java.lang.String
        可以使用通配符表示任意类型,但是必须有参数
        可以使用..表示有无参数均可,有参数可以是任意类型
全通配写法:
    * *..*.*(..)

实际开发中切入点表达式的通常写法:
    切到业务层实现类下的所有方法
    * com.itheima.service.impl.*.*(..)

一般的なポイントカット式

 <aop:pointcut id="query" expression="execution(public * com.imis.service.impl.UserServiceImpl.queryAll())"/>
<!--      配置切面指定类的方法及要切入的类的方法      -->
<!--       前置     -->
<aop:before method="before" pointcut-ref="query"></aop:before>

おすすめ

転載: blog.csdn.net/weixin_45925906/article/details/112846530