使用aop进行事务的管理(简单易懂版本)

pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>SpringAcount</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
<!--        引入和核心的context-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.1.11</version>
        </dependency>
<!--        引入juint-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
<!--        引入数据库链接-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
<!--        引入druid数据源-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
        </dependency>
<!--        引入日志配置文件-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.17.1</version>
        </dependency>
<!--        引入resource注解-->
        <dependency>
            <groupId>jakarta.annotation</groupId>
            <artifactId>jakarta.annotation-api</artifactId>
            <version>2.1.1</version>
        </dependency>
<!--        引入切面的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.3.13</version>
        </dependency>
<!--        springjdbc依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>6.1.11</version>
        </dependency>
    </dependencies>
</project>

代替这个pom文件的springconfig.class

package com.project.Util;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

import javax.sql.DataSource;

@Configuration
@ComponentScan(basePackages = {"com.project.service", "com.project.AspectLogger"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class SpringConfig {
	
	@Bean
	public DataSource dataSource() {
		DruidDataSource dataSource = new DruidDataSource();
		dataSource.setUsername("root");
		dataSource.setPassword("123456");
		dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
		dataSource.setUrl("jdbc:mysql://localhost:3306/studentdb");
		return dataSource;
	}
	
	@Bean
	public JdbcTemplate jdbcTemplate(DataSource dataSource) {
		return new JdbcTemplate(dataSource);
	}
}

logger配置文件

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/>
        </Console>
        <!--        <File name="LogFile" fileName="logs/app.log">-->
        <!--            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/>-->
        <!--        </File>-->
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
            <!--            <AppenderRef ref="LogFile"/>-->
        </Root>
    </Loggers>
</Configuration>```
## spring.xml文件配置

```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:context="http://www.springframework.org/schema/context"
       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/context
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="root"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="password" value="123456"/>
        <property name="url" value="jdbc:mysql://localhost:3306/dm"/>
    </bean>

    <!--    使用spring自带的jdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--    使用这个cglib进行代理-->
    <!--    true表示使用这个动态代理-->
    <aop:aspectj-autoproxy proxy-target-class="true"/>

    <!--    使用这个context进行包的扫描-->
    <context:component-scan base-package="com.project.service, com.project.AspectLogger"/>

</beans>

pojo接收类

package com.project.pojo;

public class User {
		private Integer 	no;
		private String 	name;
		private Integer 	age;
	
	public User(Integer no, String name, Integer age) {
		this.no = no;
		this.name = name;
		this.age = age;
	}
	
	public User() {
	}
	
	public Integer getNo() {
		return no;
	}
	
	public void setNo(Integer no) {
		this.no = no;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public Integer getAge() {
		return age;
	}
	
	public void setAge(Integer age) {
		this.age = age;
	}
	
	@Override
	public String toString() {
		return "User{" +
				"no=" + no +
				", name='" + name + '\'' +
				", age=" + age +
				'}';
	}
}

业务接口

package com.project.Dao;

import com.project.pojo.User;

import java.util.List;

/**
 * 业务逻辑代码
 */
public interface UserDao {
	
	List<User> selectAll();
	
	User selectByID(int id);
	
	int deleteByID(int id);
	
	int modifyUser(User user);
	
	int insertUser(User user);
}

业务逻辑类(Service)

package com.project.service;

import com.project.Dao.UserDao;
import com.project.Util.SpringConfig;
import com.project.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("userServiceBean")
public class UserService implements UserDao {
	static ApplicationContext context = null;
	static JdbcTemplate jdbcTemplate = null;
	
	static {
		context = new AnnotationConfigApplicationContext(SpringConfig.class);
		jdbcTemplate = context.getBean("jdbcTemplate", JdbcTemplate.class);
	}
	
	public List<User> selectAll() {
		
		String sql = "SELECT * FROM studentdb.user;";
//		if (1 == 1) {
//			throw new RuntimeException("运行异常");
//		}
		List<User> userList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
		return userList;
	}
	
	@Override
	public User selectByID(int id) {
		String sql = "SELECT * FROM studentdb.user WHERE no = ?";
		User user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), id);
		return user;
	}
	
	@Override
	public int deleteByID(int id) {
		String sql = "DELETE FROM studentdb.user WHERE no = ?";
		return jdbcTemplate.update(sql, id);
	}
	
	@Override
	public int modifyUser(User user) {
		String sql = "UPDATE studentdb.user SET name = ?, age = ? WHERE no = ?";
		return jdbcTemplate.update(sql, user.getName(), user.getAge(), user.getNo());
	}
	
	@Override
	public int insertUser(User user) {
		String sql = "INSERT INTO studentdb.user (no, name, age) VALUES (?, ?, ?)";
		return jdbcTemplate.update(sql, user.getNo(), user.getName(), user.getAge());
	}
}

事务管理类(AspectLogger)

package com.project.AspectLogger;

import com.project.pojo.User;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
@Aspect
@Order(1)
public class LoggerAspect {
	public LoggerAspect() {
//		System.out.println("你知道的这个构造方法肯定实惠别执行的");
	}
	
	//   定义切点
	@Pointcut("execution(* com.project.service..*(..))")
	public void pointCut() {
	
	}
	
	//	注册日志
	private final Logger logger = LoggerFactory.getLogger(LoggerAspect.class);
	
	@Before("pointCut()")
	public void AfterAdviceLog(JoinPoint joinPoint) {
		Signature signature = joinPoint.getSignature();
		String methodName = signature.getName();
		SimpleDateFormat format = new SimpleDateFormat("yyy-MM-dd HH-ss-SSS");
		String nowTime = format.format(new Date());
		logger.info(nowTime + "张三" + "使用了" + methodName + "方法");
	}
	
	@AfterThrowing("pointCut()")
	public void exceptionAdvice() {
		System.out.println("出现异常");
	}
	
	@Around("pointCut()")
	/**
	 * 最后只需要在这个地方添加一个事务提交的机制就ok
	 * 其实如果是这个事务的话就只需要在这个地方进行回滚 提交事务就够了
	 */
	public Object aroundAdviceLog(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out.println("开启事务");
		Object result = null; // 定义一个变量来接收返回结果
		try {
			result = joinPoint.proceed(); // 执行被拦截的方法并获取返回值
			System.out.println("提交事务");
			return result; // 返回被拦截方法的返回值
		} catch (Throwable e) {
			System.out.println("事件回滚");
			logger.info(e.getMessage());
			
			MethodSignature signature = (MethodSignature) joinPoint.getSignature();
			Class<?> returnType = signature.getReturnType();
			Object object = null;
			// 根据返回值类型进行不同的处理
			if (returnType.equals(int.class) || returnType.equals(Integer.class)) {
				object = 0;
			} else if (returnType.equals(String.class)) {
				object = "default string";
			} else if (returnType.equals(List.class)) {
				object = new ArrayList<>();
			} else {
				// 可以添加更多的类型处理
				object = null;
			}
			
			return object;
		} finally {
			System.out.println("事件结束了");
		}
	}

}


//			MethodSignature signature = (MethodSignature) joinPoint.getSignature();
  //在这个代码片段当中这个是最重要的部分他可以获取到方法的返回值的类型  原生的Signature是不能获取到这个返回值类型的
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值