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

来源:互联网 发布:大数据新手视频 编辑:程序博客网 时间:2024/04/27 04:29

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

0 0
原创粉丝点击