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>