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