您的位置:首页 > 编程语言 > Java开发

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

2017-03-13 00:39 931 查看
本文主要是带领读者实现一个小例子,来模拟 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;
这行注释去掉,引起异常。这样你就可以看到事务被回退了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息