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

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zhangchao19890805/article/details/61708089

本文主要是带领读者实现一个小例子,来模拟 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; 这行注释去掉,引起异常。这样你就可以看到事务被回退了。

展开阅读全文

没有更多推荐了,返回首页