AOP实例 – 环绕增强日志记录
一、创建商品日志记录表 Product_Log
-- 创建表
create table Product_Log(
pl_id number primary key,
action_class varchar2(100),
method_name varchar2(100),
args varchar2(100),
create_date date default sysdate
)
-- 创建序列
create sequence seq_pl start with 1;
-- 插入一条数据
insert into product_log values(seq_pl.nextval,'select()','select','eeeeeeee',sysdate)
-- 查询
select * from product_log
结果展示:
二、完成日志记录表的插入逻辑
- 先看一下我的包结构:
- 需要导入的jar包
- 日志的插入逻辑,俗称:在数据库上插入信息。过程分为:
(1)在mybatis中配置mapper文件的路径
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置数据库连接信息 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
<property name="username" value="hr"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 配置mapper文件的路径 -->
<mappers>
<mapper resource="com/gxy/dao/ProductMapper.xml"/>
<mapper resource="com/gxy/dao/ProductLogMapper.xml"/>
</mappers>
</configuration>
(2)编写mapper文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gxy.dao.ProductLogDao">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.gxy.entity.ProductLog">
<id column="pl_id" property="plId" />
<result column="action_class" property="actionClass" />
<result column="method_name" property="methodName" />
<result column="args" property="args" />
<result column="create_date" property="createDate" />
</resultMap>
<!-- 插入 -->
<insert id="insertLog">
insert into product_log values(seq_pl.nextval,#{actionClass},#{methodName},#{args},sysdate)
</insert>
</mapper>
(3)编写dao层
package com.gxy.dao;
import org.apache.ibatis.annotations.Param;
public interface ProductLogDao {
//插入
public void insertLog(@Param("actionClass")String actionClass,
@Param("methodName")String methodName,
@Param("args")String args);
}
(4)编写service层
package com.gxy.service;
public interface ProductLogService {
//插入
public void insertLog(String actionClass,String methodName,String args);
}
(5)编写service层的接口impl层
package com.gxy.service.impl;
import org.apache.ibatis.session.SqlSession;
import com.gxy.dao.ProductLogDao;
import com.gxy.service.ProductLogService;
import com.gxy.util.MyBatisUtil;
public class ProductLogServiceimpl implements ProductLogService {
//插入
public void insertLog(String actionClass, String methodName, String args) {
//获取连接
SqlSession session = MyBatisUtil.getSqlSession();
//通过代理生成对象
ProductLogDao logDao = session.getMapper(ProductLogDao.class);
//对象调方法
logDao.insertLog(actionClass, methodName, args);
//提交事务
session.commit();
//关闭流
MyBatisUtil.close();
}
}
(6)配置applicationContext.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-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<bean id="serviceimpl" class="com.gxy.service.impl.ProductServiceimpl"></bean>
<bean id="logserviceimpl" class="com.gxy.service.impl.ProductLogServiceimpl"></bean>
<!-- 前置增强功能 -->
<bean id="myBeforeAdvice" class="com.gxy.aop.MyBeforeAdvice"></bean>
<!-- 后置增强 -->
<bean id="myAfterAdvice" class="com.gxy.aop.MyAfterAdvice"></bean>
<!-- 异常增强 -->
<bean id="myThrowsAdvice" class="com.gxy.aop.MyThrowsAdvice"></bean>
<!-- 环绕增强 -->
<bean id="myInterceptor" class="com.gxy.aop.MyInterceptor"></bean>
<!-- aop的配置 -->
<aop:config>
<!-- 切入点 -->
<aop:pointcut expression="execution(* com.gxy.service.ProductService.*(..))" id="myPointCut"/>
<!-- 编织 -->
<!-- <aop:advisor advice-ref="myBeforeAdvice" pointcut-ref="myPointCut"/> -->
<!-- <aop:advisor advice-ref="myAfterAdvice" pointcut-ref="myPointCut"/> -->
<!-- <aop:advisor advice-ref="myThrowsAdvice" pointcut-ref="myPointCut"/> -->
<aop:advisor advice-ref="myInterceptor" pointcut-ref="myPointCut"/>
</aop:config>
</beans>
(7)编写环绕增强
package com.gxy.aop;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class MyInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
System.out.println("环绕增强");
//获取目标实现类对象
String actionClass = arg0.getThis().getClass().toString();
System.out.println("arg0.getThis():"+actionClass);
//获取目标方法名称
String methodName = arg0.getMethod().getName();
System.out.println("arg0.getMethod():"+methodName);
//获取目标方法参数的实参列表
Object[] arg = arg0.getArguments();
for (int i = 0; i < arg.length; i++) {
System.out.println("arg0.getArguments():"+arg[i]);
}
//由于启动了环绕增强,目标类的方法将不会执行,而被.proceed取代,并返回目标类的反参
//执行目标方法
Object object = arg0.proceed();
return object;
}
}
(8)测试
package com.gxy.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.gxy.service.ProductLogService;
public class TestMain {
@Test
public void method1(){
//加载Spring主配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext.xml");
//根据Bean ID,由工厂创建对象
ProductLogService logService = (ProductLogService)context.getBean("logserviceimpl");
logService.insertLog("insert()", "insert", "aaaa");
}
}
三、环绕增强搜集日志记录参数,并测试
- 在环绕增强中搜集日志,记录参数
package com.gxy.aop;
import java.util.Arrays;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.gxy.service.ProductLogService;
import com.gxy.service.impl.ProductLogServiceimpl;
public class MyInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
System.out.println("环绕增强");
//获取目标实现类对象
String actionClass = arg0.getThis().getClass().toString();
System.out.println("arg0.getThis():"+actionClass);
//获取目标方法名称
String methodName = arg0.getMethod().getName();
System.out.println("arg0.getMethod():"+methodName);
//获取目标方法参数的实参列表
Object[] arg = arg0.getArguments();
for (int i = 0; i < arg.length; i++) {
System.out.println("arg0.getArguments():"+arg[i]);
}
String args = Arrays.toString(arg);
//加载Spring主配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext.xml");
ProductLogService logService = (ProductLogService)context.getBean("logserviceimpl");
logService.insertLog(actionClass, methodName, args);
//由于启动了环绕增强,目标类的方法将不会执行,而被.proceed取代,并返回目标类的反参
//执行目标方法
Object object = arg0.proceed();
return object;
}
}
- 测试(这里是product项目中的修改功能,当执行修改时,将会添加此条记录)
package com.gxy.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.gxy.service.ProductService;
public class TestMain {
//加载Spring主配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext.xml");
@Test
public void test1(){
//根据Bean ID,由工厂创建对象
ProductService productService=(ProductService)context.getBean("serviceimpl");
//修改
productService.updateProduct("华硕007", "开机速度为1秒", 5632.0, 21);
}
}