装饰器模式、JDK动态代理和CGLIB动态代理三种AOP实现

AOP即对OOP的补充,面向切面的编程方式增强面向对象思想的功能,概念之类的问题这里不做阐述,直接上代码实现细节,具体原理需要深入源码理解。

测试功能,定义一个普通service类,利用AOP不修改原来类代码实现嵌入这个类的日志打印。

定义一个DAO接口:

public interface DAO {
    public boolean insert();
    public boolean update();
    public boolean delete();
}

DAO接口实现类:

public class UserDAOImpl implements DAO {
    @Override
    public boolean insert() {
        System.out.println("UserDAOImpl.insert()");
        return false;
    }

    @Override
    public boolean update() {
        System.out.println("UserDAOImpl.update()");
        return false;
    }

    @Override
    public boolean delete() {
        System.out.println("UserDAOImpl.delete()");
        return false;
    }
}

1、最简单的装饰器模式实现AOP,传入对象并做逐一对各方法进行细节功能增强。体现为实例的获取细节发生变更,使之得到一个对原本实现类的细节增强装饰类。

装饰类:

package com.AOP.Decorator;

import com.AOP.DAO;

/**
 * ***************************************************************************
 * Description  : 装饰器模式 核心就是实现Dao接口并持有Dao接口的引用(实例化时传入已实现该接口的实现类,再调用方法)
 * Author       : cxx
 * Creation date: 2017/10/26.
 * Version      : 1.0
 * ***************************************************************************
 */
public class DAODecorator implements DAO {
    private DAO dao;
    public DAODecorator(DAO dao){
        this.dao = dao;
    }
    @Override
    public boolean insert() {
        System.out.println("DAODecorator -> " + dao.getClass().getName() + "-> Before insert()" );
        boolean flag = dao.insert();
        System.out.println("DAODecorator -> " + dao.getClass().getName() + "-> After insert()" );
        return flag;
    }

    @Override
    public boolean update() {
        System.out.println("DAODecorator -> " + dao.getClass().getName() + "-> Before update()" );
        boolean flag = dao.update();
        System.out.println("DAODecorator -> " + dao.getClass().getName() + "-> After update()" );
        return flag;
    }

    @Override
    public boolean delete() {
        return dao.delete();
    }
}

测试类最后做统一输入展示。

2、jdk动态代理实现AOP,使用jdk代理实现产生新的增强AOP实现类,依赖反射实现,方法拦截后判断方法名再做更新(Spring AOP实现方式之一),这种方式仅针对接口实现的实例类。

JDK代理实现类:

package com.AOP.JDKProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * ***************************************************************************
 * Description  : 代理模式 jdk中提供的代理实现方法 依赖反射;在判断方法名称之后执行所需增加的业务
 * Author       : cxx
 * Creation date: 2017/10/26.
 * Version      : 1.0
 * ***************************************************************************
 */
public class DaoInvocationHandler implements InvocationHandler {
    private Object object;

    public DaoInvocationHandler(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        if ("insert".equals(methodName) || "update".equals(methodName)) {
            System.out.println("DaoInvocationHandler -> " + object.getClass().getName() + "-> Before insert()");
            Object retObj = method.invoke(object, args);
            System.out.println("DaoInvocationHandler -> " + object.getClass() + "-> After insert()");
            return retObj;
        }
        return method.invoke(object, args);
    }
}

测试类最后做统一输入展示。

3、CGLIB代理增强实现AOP,但并非是对jdk动态代理AOP的实现进行增强,区别于jdk能实现对接口的代理,CGLIB能实现对类的代理。

CGLIB代理实现类:

package com.AOP.CGLIBProxy;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
/**
 * ***************************************************************************
 * Description  :使用CGLIB解决了JDK的Proxy无法针对类做代理的问题,
 * 但是这里要专门说明一个问题:使用装饰器模式可以说是对使用原生代码的一种改进,使用Java代理可以说是对于使用装饰器模式的一种改进,
 * 但是使用CGLIB并不是对于使用Java代理的一种改进。
 * Author       : cxx
 * Creation date: 2017/10/26.
 * Version      : 1.0
 * ***************************************************************************
 */
public class CglibDaoProxy implements MethodInterceptor {
    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        String methodName = method.getName();
        if ("insert".equals(methodName) || "update".equals(methodName)) {
            System.out.println("CglibDaoProxy -> " + object.getClass().getName() + "-> Before insert()");
            Object result = proxy.invokeSuper(object, args);
            System.out.println("CglibDaoProxy -> " + object.getClass().getName() + "-> After insert()");
            return result;
        }
        Object result = proxy.invokeSuper(object, args);
        return result;
    }
}

测试类最后做统一输入展示。

main方法测试类:

package com.AOP;

import com.AOP.CGLIBProxy.CglibDaoProxy;
import com.AOP.Decorator.DAODecorator;
import com.AOP.JDKProxy.DaoInvocationHandler;
import com.AOP.impl.UserDAOImpl;
import net.sf.cglib.proxy.Enhancer;
import java.lang.reflect.Proxy;

public class UseDAOTest {
    public static void main(String[] args) {
        //装饰器模式 实现调用
        DAO dao = new DAODecorator(new UserDAOImpl());
        dao.insert();
        dao.update();
        dao.delete();
        System.out.println("执行类:" + dao.getClass().getName());
        System.out.println();

        //jdk动态代理模式实现调用
        DAO dao1 = new UserDAOImpl();
        //数组中参数DAO.class即为需要实现增加业务的类,如其它实现了DAO的类也需要增加业务则数组中增加那个实现类
        DAO proxyDao = (DAO) Proxy.newProxyInstance(DaoInvocationHandler.class.getClassLoader(),
                new Class[]{DAO.class}, new DaoInvocationHandler(dao1));
        proxyDao.insert();
        proxyDao.update();
        proxyDao.delete();
        System.out.println("执行类:" + proxyDao.getClass().getName());
        System.out.println();

        //CGLIB代理模式实现调用
        CglibDaoProxy daoProxy = new CglibDaoProxy();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserDAOImpl.class);
        enhancer.setCallback(daoProxy);
        DAO dao2 = (UserDAOImpl) enhancer.create();
        dao2.insert();
        boolean flag = dao2.update();
        dao2.delete();
        System.out.println("执行类:" + dao2.getClass().getName());

    }

}

控制台输入结果:

DAODecorator -> com.AOP.impl.UserDAOImpl-> Before insert()
UserDAOImpl.insert()
DAODecorator -> com.AOP.impl.UserDAOImpl-> After insert()
DAODecorator -> com.AOP.impl.UserDAOImpl-> Before update()
UserDAOImpl.update()
DAODecorator -> com.AOP.impl.UserDAOImpl-> After update()
UserDAOImpl.delete()
执行类:com.AOP.Decorator.DAODecorator

DaoInvocationHandler -> com.AOP.impl.UserDAOImpl-> Before insert()
UserDAOImpl.insert()
DaoInvocationHandler -> class com.AOP.impl.UserDAOImpl-> After insert()
DaoInvocationHandler -> com.AOP.impl.UserDAOImpl-> Before insert()
UserDAOImpl.update()
DaoInvocationHandler -> class com.AOP.impl.UserDAOImpl-> After insert()
UserDAOImpl.delete()
执行类:com.sun.proxy.$Proxy0

CglibDaoProxy -> com.AOP.impl.UserDAOImpl$$EnhancerByCGLIB$$bd2466cc-> Before insert()
UserDAOImpl.insert()
CglibDaoProxy -> com.AOP.impl.UserDAOImpl$$EnhancerByCGLIB$$bd2466cc-> After insert()
CglibDaoProxy -> com.AOP.impl.UserDAOImpl$$EnhancerByCGLIB$$bd2466cc-> Before insert()
UserDAOImpl.update()
CglibDaoProxy -> com.AOP.impl.UserDAOImpl$$EnhancerByCGLIB$$bd2466cc-> After insert()
UserDAOImpl.delete()
执行类:com.AOP.impl.UserDAOImpl$$EnhancerByCGLIB$$bd2466cc

 

你可能感兴趣的:(JAVA基础)