Spring 之 AOP 动态代理实现原理
什么是代理?
指为一个目标对象提供一个代理对象, 并由代理对象控制对目标对象的引用. 使用代理对象, 是为了在不修改目标对象的基础上, 增强目标对象的业务逻辑。
动态代理
静态代理会为每一个业务增强都提供一个代理类, 由代理类来创建代理对象, 而动态代理并不存在代理类, 代理对象直接由代理生成工具动态生成.
JDK动态代理是使用 java.lang.reflect 包下的代理类来实现。JDK动态代理动态代理必须要有接口。
添加用户的接口
package cn.et.dao;
public interface UserDao {
public void addUser();
}
实现添加用户接口:
package cn.et.dao.impl;
import cn.et.dao.UserDao;
public class UserDaoImpl implements UserDao {
public void addUser(){
System.out.println("添加用户");
}
}
未集成或实现的接口(cglib代理,用来和jdk实现做对比)
package cn.et.dao.impl;
public class StudentDao {
public void addStudent(){
System.out.println("添加学生");
}
}
JDK实现代理InvocationHandler
package cn.et.utils;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler{
private Object targetObj;
public MyInvocationHandler(Object targetObj){
this.targetObj = targetObj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("权限验证");
Object resultObj = method.invoke(targetObj, args);
System.out.println("日志记录");
return resultObj;
}
}
package cn.et.utils;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
return enhancer.create();
}
//实现MethodInterceptor接口方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("权限验证");
Object result = proxy.invokeSuper(obj, args);
System.out.println("日志记录");
return result;
}
}
package cn.et.utils;
import java.lang.reflect.Proxy;
import org.junit.Test;
import cn.et.dao.UserDao;
import cn.et.dao.impl.StudentDao;
import cn.et.dao.impl.UserDaoImpl;
public class Checkout {
@Test
public void Testing(){
UserDao userDao = new UserDaoImpl();
/*
Spring AOP(面向切面编程),扩展功能不修改源代码实现,采用横向抽取机制,取代了传统纵向继承体系重复性代码
横向抽取机制,底层使用动态代理方式实现
针对有接口的情况时使用JDK中的java.lang.reflect类库提供的动态代理
针对没有接口的情况时,使用Cglib框架提供的动态代理
*/
MyInvocationHandler handler = new MyInvocationHandler(userDao);
UserDao proxyUserDao = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(),handler);
proxyUserDao.addUser();
System.out.println("。。。。。。。。。。。。。");
CglibProxy proxy = new CglibProxy();
StudentDao proxyImp = (StudentDao)proxy.getProxy(StudentDao.class);
proxyImp.addStudent();
}
}
模拟Spring AOP场景
了解了动态代理后, 我们就可以自己来实现Spring AOP功能了, 所以下面我们来模拟下Spring AOP场景。
(1) 转账业务
public interface IAccountService {
//主业务逻辑: 转账
void transfer();
}
public class AccountServiceImpl implements IAccountService {
@Override
public void transfer() {
System.out.println("调用dao层,完成转账主业务.");
}
}
(2) 切面抽象类
定义一个切面抽象类, 该类使用了模板方法的设计模式, 为开始, 结束, 异常, 前置增强, 后置增强提供了默认实现, 当我们定义切面类时只需要按需重写它们就行. isIntercept()
方法用来判断切入点是否正确, 切面类需要重写这个方法
public abstract class BaseAspect implements MethodInterceptor {
private static final Logger logger = LoggerFactory.getLogger(BaseAspect.class);
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object result = null;
begin();
try {
if (isIntercept(method, args)) {
before();
result = methodProxy.invokeSuper(obj, args);
after();
} else {
result = methodProxy.invokeSuper(obj,args);
}
} catch (Exception e) {
logger.error("proxy failure", e);
error(e);
throw e;
} finally {
end();
}
return result;
}
/**
* 开始增强
*/
public void begin() {
}
/**
* 切入点判断
*/
public boolean isIntercept(Method method, Object[] args) throws Throwable {
return true;
}
/**
* 前置增强
*/
public void before() throws Throwable {
}
/**
* 后置增强
*/
public void after() throws Throwable {
}
/**
* 异常增强
*/
public void error(Throwable e) {
}
/**
* 最终增强
*/
public void end() {
}
}
AOP 思想: 基于代理思想,对原来目标对象,创建代理对象,在不修改原对象代码情况下,通过代理对象,调用增强功能的代码,从而对原有业务方法进行增强 !
AOP应用场景
场景一: 记录日志
场景二: 监控方法运行时间 (监控性能)
场景三: 权限控制
场景四: 缓存优化 (第一次调用查询数据库,将查询结果放入内存对象, 第二次调用, 直接从内存对象返回,不需要查询数据库 )
场景五: 事务管理 (调用方法前开启事务, 调用方法后提交关闭事务 )
相关文章:
Spring 之 AOP 动态代理实现原理
Spring AOP原理之动态代理
Spring AOP的实现原理及应用场景(通过动态代理)
spring源码解析之AOP原理
为者常成,行者常至
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)