什么叫代理:通过代理对象来访问真实对象的方法。代理商代理厂家产品。
完成代理,需要两步骤:
- 建立代理对象与真实对象的代理关系,返回代理对象,代理对象类型是真实对象类型。
- 实现代理对象调用真实对象方法的代理逻辑:在调用真实方法前,或后,或异常情况下的一些处理
代理技术有两种
- JDK动态代理:InvocationHandler
- CGLIB动态代理:第三方包,MethodInterceptor
应用场景:
- 事务管理
- Controller通知,控制器通知
- Spring 缓存管理器
JDK动态代理
实现InvocationHandler,
- 建立代理对象与真实对象的代理关系,返回代理对象:代理对象可以访问真实对象接口下的所有方法,如果真实对象没有实现接口,不能被jdk代理。
- 实现代理逻辑
- public class JdkProxyTest implements InvocationHandler {
private Object realObject;
/**
* 建立代理对象与真实对象的对应关系
* @param targetObject 真实对象,要求必须有实现的接口
* @return 代理对象,类型与真实对象一致
*/
public Object getProxy(Object targetObject) {
this.realObject = targetObject;
return Proxy.newProxyInstance(
targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
this //当前对象实例作为代理对象
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//spring事务管理,执行SQL前先获取数据库连接
System.out.println("在目标方法执行前执行的逻辑");
Object value = null;
try {
//在执行目标函数之前,通过责任链模式,执行拦截器,当所有的拦截器都执行通过时,才能执行目标函数,
// 在handlerAdapter里,就是先执行拦截器,在执行控制器方法的,封装成了HandlerExecutionChain
//执行业务逻辑
value = method.invoke(realObject,args);
} catch (Exception e) {
e.printStackTrace();
//当目标方法执行出现异常时,spring事务管理回滚事务.
System.out.println("在目标方法执行出现异常时执行的逻辑");
}
//spring事务管理,在执行完目标方法时,释放数据库连接
System.out.println("在目标方法执行后执行的逻辑");
return value;
}
}
CGLIB动态代理
第三方包,实现MethodInterceptor接口
- 建立代理对象与真实对象的对应关系:真实对象可以没有实现接口,代理对象类型是真实对象类型
- 实现代理逻辑:
- pubic class CgibProxyTest impements MethodInterceptor { /** * 创建代理对象与真实对象的对应关系 * @param cz 真实对象 * @return 返回代理对象 */ pubic Object getProxy(Cass clz) { //增强类 Enhancer enhancer = new Enhancer(); //设置真实对象 enhancer.setSupercass(clz); //设置当前实例对象为代理对象 enhancer.setCalback(this); return enhancer.create(); } @Override pubic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwabe { //spring事务管理,执行SQL前先获取数据库连接 System.out.printn("在目标方法执行前执行的逻辑"); Object resut = nul; try {
//在执行目标函数之前,通过责任链模式,执行拦截器,当所有的拦截器都执行通过时,才能执行目标函数,
// 在handlerAdapter里,就是先执行拦截器,在执行控制器方法的,封装成了HandlerExecutionChain
//执行业务逻辑
result = methodProxy.invokeSuper(proxy,args);
} catch (Exception e) {
e.printStackTrace();
//当目标方法执行出现异常时,spring事务管理回滚事务.
System.out.println("在目标方法执行出现异常时执行的逻辑");
}
//spring事务管理,在执行完目标方法时,释放数据库连接
System.out.println("在目标方法执行后执行的逻辑");
return result;
}
}