【069】Java利用动态代理模拟实现Spring的AOP(面向切面编程)功能的小实践

通过Java动态代理实现面向切面编程(AOP)的小例子,演示如何为特定方法添加事务处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要是带领读者实现一个小例子,来模拟 Spring 框架的面向切面编程(AOP)。实现过程中用到了 Java 的动态代理。

整个项目由maven管理。
pom.xml

<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>zhangchao</groupId>
	<artifactId>AOP</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>
</project>

目录结构

src/main/java
  │
  └─ zhangchao
        │
        ├─ dao
        │    └ UserDao.java
        │
        ├─ framework
        │    ├ Factory.java
        │    ├ TransactionInterceptor.java
        │    └ ZcInvocationHandler.java
        │    
        ├─ po
        │    └ User.java
        │
        ├─ service
        │    ├─ impl
        │    │    └ UserServiceImpl.java
        │    │
        │    └─ UserService.java  
        │      
        └─ Main.java

实体类User

package zhangchao.po;

public class User {
	String id;
	String name;
	Integer age;
}

UserDao封装数据库操作

package zhangchao.dao;

public class UserDao {
	public void save() {
		System.out.println("save user");
	}
}

工厂类Factory。这里使用了 Java 动态代理。表面上看是根据className返回每个类对应生成的对象,事实上是返回的是代理对象。每当生成代理对象的时候,就会调用接口InvocationHandler的invoke方法。

package zhangchao.framework;

import java.lang.reflect.Proxy;

public final class Factory {
	public final static Object getBean(String className) {
		Object bean = null;
		try {
			Class<?> c = Class.forName(className);
			Object realBean = c.newInstance();
			bean = Proxy.newProxyInstance(c.getClassLoader(), c.getInterfaces(), 
					new ZcInvocationHandler(realBean));
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return bean;
	}
}

ZcInvocationHandler类实现了InvocationHandler接口。在继承的invoke方法里,所有save字符串开头的方法都要做事务处理。事务处理的代码在TransactionInterceptor类中。

package zhangchao.framework;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ZcInvocationHandler implements InvocationHandler {
	private Object bean;
	
	TransactionInterceptor ti = new TransactionInterceptor();
	
	ZcInvocationHandler(Object bean) {
		this.bean = bean;
	}
	
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		String methodName = method.getName();
		if (methodName.startsWith("save")) {
			ti.begin();
			try {
				method.invoke(bean, args);
				ti.commit();
			} catch (Exception e) {
				ti.rollBack();
			}
		} else {
			method.invoke(bean, args);
		}
		return null;
	}

}

TransactionInterceptor类用来处理事务。

package zhangchao.framework;

public class TransactionInterceptor {
	public void begin () {
		System.out.println("开始事务");
	}
	
	public void commit() {
		System.out.println("提交事务");
	}
	
	public void rollBack() {
		System.out.println("回滚事务");
	}
}

服务类的接口:

package zhangchao.service;

import zhangchao.po.User;

public interface UserService {
	void save(User user);
}

服务类的实现:

package zhangchao.service.impl;

import zhangchao.dao.UserDao;
import zhangchao.po.User;
import zhangchao.service.UserService;

public class UserServiceImpl implements UserService {
	
	private UserDao userDao = new UserDao();

	public void save(User user) {
		userDao.save();
//		int r = 4/0;
	}
}

Main.java

package zhangchao;

import zhangchao.framework.Factory;
import zhangchao.po.User;
import zhangchao.service.UserService;

public class Main {

	public static void main(String[] args) {
		UserService userDao = (UserService)Factory.getBean("zhangchao.service.impl.UserServiceImpl");
		userDao.save(new User());
	}

}

在 UserServiceImpl 类中,可以把 int r = 4/0; 这行注释去掉,引起异常。这样你就可以看到事务被回退了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值