1、代理模式模式的定义
代理模式(Proxy Pattern)定义:指为其他对象提供一种代理,以控制对这个对象的访问,属于结构型设计模式。
在某些情况下,访问对象不适合或者不能直接引用目标对象,这时,可以通过代理对象来间接控制对该对象的访问,而代理对象可以在访问对象和目标对象之间起到中介的作用。
使用代理模式的主要目的:
2、代理模式模式的结构
(1)模式的结构
代理模式的主要角色如下。
在代码中,一般代理会被理解为代码增强,实际上就是在原代码逻辑前后增加一些代码逻辑,而使调用者无感知。
根据代理的创建时期,代理模式分为静态代理和动态代理。
(2)结构图如下:(图来自网络)
3、优缺点
代理模式的主要优点有:
其主要缺点是:
那么如何解决以上提到的缺点呢?答案是可以使用动态代理方式
4、使用场景
5、模式的通用实现
代码如下:
public class ProxyPattern {
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.Request();
}
}
//抽象主题
interface Subject {
void Request();
}
//真实主题
class RealSubject implements Subject {
@Override
public void Request() {
System.out.println("访问真实主题方法...");
}
}
//代理
class Proxy implements Subject {
private RealSubject realSubject;
@Override
public void Request() {
if (realSubject == null) {
realSubject = new RealSubject();
}
preRequest();
realSubject.Request();
postRequest();
}
public void preRequest() {
System.out.println("访问真实主题之前的预处理。");
}
public void postRequest() {
System.out.println("访问真实主题之后的后续处理。");
}
}
下面代码主要是对真实类的方法做事务增强,方法没有做具体的业务实现。
静态代理:由程序员创建或特定工具自动生成源代码并对其编译。在程序运行之前,就已经存在代理类的字节码文件(代理类.class),代理对象和真实对象的关系也已经确定了。
静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同的父类。
1、正常创建model、dao 和 service
UserDao类
public class UserDao implements IUserDao {
@Override
public void save(User user) {
System.out.println("保存用户");
}
@Override
public void update(User user) {
System.out.println("修改用户");
}
@Override
public List listAll() {
System.out.println("查询所有");
return new ArrayList<>();
}
}
UserServiceImpl类
public class UserServiceImpl implements IUserService {
private UserDao userDao;
public UserServiceImpl() {
}
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save(User user) {
userDao.save(user);
System.out.println("保存成功");
}
@Override
public void update(User user) {
userDao.update(user);
throw new RuntimeException("修改失败");
}
@Override
public List listAll() {
System.out.println("查询成功");
return userDao.listAll();
}
}
2、创建事务的处理类和代理类
MyTransctionManager类
//模拟事务管理器
public class MyTransctionManager {
public void begin() {
System.out.println("开启事务");
}
public void commit() {
System.out.println("提交事务");
}
public void cloce() {
System.out.println("关闭事务");
}
public void rollback() {
System.out.println("回滚事务");
}
}
UserServiceProxy类
public class UserServiceProxy implements IUserService{
private IUserService target; //真实对象
private MyTransctionManager txManager; //事务管理器
public UserServiceProxy(IUserService target, MyTransctionManager txManager) {
this.target = target;
this.txManager = txManager;
}
@Override
public void save(User user) {
txManager.begin();
try {
target.save(user);
txManager.commit();
} catch (Exception e) {
e.printStackTrace();
txManager.rollback();
} finally {
txManager.cloce();
}
}
@Override
public void update(User user) {
txManager.begin();
try {
target.update(user);
txManager.commit();
} catch (Exception e) {
e.printStackTrace();
txManager.rollback();
} finally {
txManager.cloce();
}
}
@Override
public List listAll() {
return target.listAll();
}
}
3、测试
public class App {
public static void main(String[] args) {
testNoProxy();
testProxy();
}
// 使用静态代理
private static void testProxy() {
User user = new User();
//属性注入,多态
IUserService userService = new UserServiceProxy(new UserServiceImpl(new UserDao()), new MyTransctionManager());
userService.save(user);
System.out.println("==========");
userService.update(user);
System.out.println("==========");
userService.listAll();
}
// 未使用代理
private static void testNoProxy() {
User user = new User();
IUserService userService = new UserServiceImpl(new UserDao());
userService.save(user);
System.out.println("==========");
userService.update(user);
System.out.println("==========");
userService.listAll();
}
}
4、静态代理总结
优点:可以做到在符合开闭原则(软件组成实体应该是可扩展的, 但是不可修改)的情况下对目标对象进行功能扩展。
缺点:我们得为每一个服务都得创建代理类,工作量太大,不易管理。同时接口一旦发生改变,代理类也得相应修改。
动态代理:动态代理类是在程序运行期间由JVM通过反射等机制动态创建生成的,所以不存在代理类的字节码文件,代理对象和真实对象的关系是在程序运行时期才确定的。
动态代理的实现方式:
1)针对有接口的类:使用JDK动态代理,也叫接口动态代理
2)针对没有接口的类:使用CGLIB动态代理或者Javassist组件
如何动态的加载一份字节码:
由于JVM通过字节码的二进制信息加载类的,如果我们在运行期系统中,遵循Java编译系统组织的 .class文件的格式和结构,生成相应的二进制数据,然后再把这个二进制数据加载转换为对应的类,所以,就可完成在代码中动态创建一个类的能力。
要实现基于JDK动态代理,必须要求真实对象要有实现的接口,同时需要理解JDK中的 java.lang.reflect.Proxy类和 java.lang.reflect.InvocationHandler接口。
Proxy 类提供了创建动态代理类及其对象的静态方法,它也是由这些方法创建的所有动态代理类的父类。
static Object |
newProxyInstance(ClassLoader loader, 类>[] interfaces, InvocationHandler handler) 返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序。 |
参数
loader - 类加载器来定义代理类,一般传递真实对象的类加载器
interfaces - 代理类需要实现的接口列表
handler - 代理对象调用的增强处理方法
InvocationHandler 接口是通用处理器接口,是由代理实例的调用处理程序实现的接口
Object |
invoke(Object proxy, Method method, Object[] args) 处理代理实例上的方法调用并返回结果。 |
参数
proxy - 生成的代理对象
method - 当前调用的真实方法对象
args - 当前调用真实方法的实参
JDK动态代理使用步骤
1)新建一个接口,并为该接口创建一个实现类
2)创建自己需要增强的代码处理器,实现 InvocationHandler接口,并提供一个创建动态代理对象的方法
3)获取动态代理对象,测试
1)model、dao、service 和事务的处理类同上,然后创建增强的代码处理器类
JDKTransctionManagerAdvice类
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKTransctionManagerAdvice implements java.lang.reflect.InvocationHandler {
private Object target; //真实对象(对谁做增强)
private MyTransctionManager txManager; //事务管理器(模拟)
public void setTarget(Object target) {
this.target = target;
}
public void setTxManager(MyTransctionManager txManager) {
this.txManager = txManager;
}
//为真实对象的方法做增强的具体操作
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("==" + proxy.getClass()); //class com.sun.proxy.$Proxy0
if (method.getName().startsWith("get") || method.getName().startsWith("list")) {
return method.invoke(target, args); //放行
}
Object ret = null;
txManager.begin();
try {
ret = method.invoke(target, args); //调用真实对象的方法
txManager.commit();
} catch (Exception e) {
e.printStackTrace();
txManager.rollback();
} finally {
txManager.cloce();
}
return ret;
}
//创建一个代理对象
public T getProxyObject() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), //类加载器,一般跟上真实对象的类加载器
target.getClass().getInterfaces(), //真实对象所实现的接口(JDK动态代理必须要求真实对象有接口)
this);//做事务增强的对象,InvocationHandler子类,多态
}
}
2)测试
public class App {
public static void main(String[] args) {
JDKProxy();
}
//JDK代理对象:class com.sun.proxy.$Proxy0
private static void JDKProxy() {
User user = new User();
IUserService userService = new UserServiceImpl(new UserDao());
JDKTransctionManagerAdvice advice = new JDKTransctionManagerAdvice();
advice.setTarget(userService);
advice.setTxManager(new MyTransctionManager());
IUserService proxyObject = advice.getProxyObject();
System.out.println(proxyObject.getClass()); //
// proxyObject.save(user);
System.out.println("==========");
proxyObject.update(user);
System.out.println("==========");
// proxyObject.listAll();
}
JDK动态代理原理
通过 DynamicProxyClassGenerator类生产动态代理的字节码文件,在通过反编译工具生成java文件查看
DynamicProxyClassGenerator类
import sun.misc.ProxyGenerator;
public class DynamicProxyClassGenerator {
public static void main(String[] args) throws Exception {
generateClassFile(UserServiceImpl.class, "UserServiceProxy");
}
//生成代理类的字节码文件-->Java反编译工具-->Java文件
public static void generateClassFile(Class targetClass, String proxyName) throws Exception {
//根据类信息和提供的代理类名称,生成字节码
byte[] classFile = ProxyGenerator.generateProxyClass(proxyName, targetClass.getInterfaces());
String path = targetClass.getResource(".").getPath();
System.out.println(path);
FileOutputStream out = null;
//保留到硬盘中
out = new FileOutputStream(path + proxyName + ".class");
out.write(classFile);
out.close();
}
}
反编译生成的UserServiceProxy类
import cn.jq.springdemo.model.User;
import cn.jq.springdemo.service.IUserService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.List;
public final class UserServiceProxy extends Proxy implements IUserService {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m4;
private static Method m5;
private static Method m0;
public UserServiceProxy(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void update(User var1) throws {
try {
super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void save(User var1) throws {
try {
super.h.invoke(this, m4, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final List listAll() throws {
try {
return (List)super.h.invoke(this, m5, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("cn.jq.springdemo.service.IUserService").getMethod("update", Class.forName("cn.jq.springdemo.model.User"));
m4 = Class.forName("cn.jq.springdemo.service.IUserService").getMethod("save", Class.forName("cn.jq.springdemo.model.User"));
m5 = Class.forName("cn.jq.springdemo.service.IUserService").getMethod("listAll");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
可看到
1)代理类继承了 Proxy类并且实现了要代理的接口,由于java不支持多继承,所以JDK动态代理不能代理类
2)重写了equals、hashCode、toString
3)有一个静态代码块,通过反射或者代理类的所有方法
4)通过invoke执行代理类中的目标方法doSomething
JDK动态代理需要实现类通过接口定义业务方法,对于没有接口的类,就可以使用CGLib动态代理
1)创建无接口的service 类和事务的处理类同上,然后创建增强的代码处理器类
UserServiceImpl2类 无接口
public class UserServiceImpl2 {
private UserDao userDao;
public UserServiceImpl2() {
}
public UserServiceImpl2(UserDao userDao) {
this.userDao = userDao;
}
public void save(User user) {
userDao.save(user);
System.out.println("保存成功");
}
public void update(User user) {
userDao.update(user);
throw new RuntimeException("修改失败");
}
public List listAll() {
System.out.println("查询成功");
return userDao.listAll();
}
}
CGLIBTransctionManagerAdvice类
import org.springframework.cglib.proxy.Enhancer;
import java.lang.reflect.Method;
public class CGLIBTransctionManagerAdvice implements org.springframework.cglib.proxy.InvocationHandler {
private Object target; //真实对象(对谁做增强)
private MyTransctionManager txManager; //事务管理器(模拟)
public void setTarget(Object target) {
this.target = target;
}
public void setTxManager(MyTransctionManager txManager) {
this.txManager = txManager;
}
//如何为真实对象的方法做增强的具体操作
@Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
if (method.getName().startsWith("get") || method.getName().startsWith("list")) {
return method.invoke(target, args); //放行
}
Object ret = null;
txManager.begin();
try {
ret = method.invoke(target, args); //调用真实对象的方法
txManager.commit();
} catch (Exception e) {
e.printStackTrace();
txManager.rollback();
} finally {
txManager.cloce();
}
return ret;
}
//创建一个代理对象
public T getProxyObject() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());//将继承于哪一个类,去做增强
enhancer.setCallback(this);//设置增强的对象
return (T) enhancer.create();//创建代理对象
}
}
2)测试
public class App {
public static void main(String[] args) {
CGLIBProxy();
}
//CGLIB代理对象:class cn.jq.springdemo.service.impl.UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4
private static void CGLIBProxy() {
// 生成字节码文件
// System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"E:/Lei");
User user = new User();
CGLIBTransctionManagerAdvice advice = new CGLIBTransctionManagerAdvice();
advice.setTarget(new UserServiceImpl2(new UserDao()));
advice.setTxManager(new MyTransctionManager());
UserServiceImpl2 proxyObject = advice.getProxyObject();
System.out.println(proxyObject.getClass()); //
proxyObject.save(user);
System.out.println("==========");
proxyObject.update(user);
System.out.println("==========");
proxyObject.listAll();
}
}
CGLib动态代理原理
动态代理的字节码文件反编译之后的 java文件
package cn.jq.springdemo.service.impl;
import cn.jq.springdemo.dao.impl.UserDao;
import cn.jq.springdemo.model.User;
import java.lang.reflect.Method;
import java.util.List;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.UndeclaredThrowableException;
public class UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4 extends UserServiceImpl2 implements Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private InvocationHandler CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$update$0;
private static final Method CGLIB$save$1;
private static final Method CGLIB$listAll$2;
private static final Method CGLIB$equals$3;
private static final Method CGLIB$toString$4;
private static final Method CGLIB$hashCode$5;
private static final Method CGLIB$clone$6;
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$update$0 = Class.forName("cn.jq.springdemo.service.impl.UserServiceImpl2").getDeclaredMethod("update", Class.forName("cn.jq.springdemo.model.User"));
CGLIB$save$1 = Class.forName("cn.jq.springdemo.service.impl.UserServiceImpl2").getDeclaredMethod("save", Class.forName("cn.jq.springdemo.model.User"));
CGLIB$listAll$2 = Class.forName("cn.jq.springdemo.service.impl.UserServiceImpl2").getDeclaredMethod("listAll");
CGLIB$equals$3 = Class.forName("java.lang.Object").getDeclaredMethod("equals", Class.forName("java.lang.Object"));
CGLIB$toString$4 = Class.forName("java.lang.Object").getDeclaredMethod("toString");
CGLIB$hashCode$5 = Class.forName("java.lang.Object").getDeclaredMethod("hashCode");
CGLIB$clone$6 = Class.forName("java.lang.Object").getDeclaredMethod("clone");
}
public final void update(User var1) {
try {
InvocationHandler var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
var10000.invoke(this, CGLIB$update$0, new Object[]{var1});
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void save(User var1) {
try {
InvocationHandler var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
var10000.invoke(this, CGLIB$save$1, new Object[]{var1});
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final List listAll() {
try {
InvocationHandler var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return (List)var10000.invoke(this, CGLIB$listAll$2, new Object[0]);
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
}
public final boolean equals(Object var1) {
try {
InvocationHandler var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return (Boolean)var10000.invoke(this, CGLIB$equals$3, new Object[]{var1});
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String toString() {
try {
InvocationHandler var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return (String)var10000.invoke(this, CGLIB$toString$4, new Object[0]);
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
}
public final int hashCode() {
try {
InvocationHandler var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return ((Number)var10000.invoke(this, CGLIB$hashCode$5, new Object[0])).intValue();
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
}
protected final Object clone() throws CloneNotSupportedException {
try {
InvocationHandler var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000.invoke(this, CGLIB$clone$6, new Object[0]);
} catch (Error | CloneNotSupportedException | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
}
public UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4() {
CGLIB$BIND_CALLBACKS(this);
}
public UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4(UserDao var1) {
super(var1);
CGLIB$BIND_CALLBACKS(this);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
}
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4 var1 = (UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4)var0;
if (!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if (var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if (var10000 == null) {
return;
}
}
var1.CGLIB$CALLBACK_0 = (InvocationHandler)((Callback[])var10000)[0];
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4 var10000 = new UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4 var10000 = new UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4 var10000 = new UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4;
switch(var1.length) {
case 0:
var10000.();
break;
case 1:
if (var1[0].getName().equals("cn.jq.springdemo.dao.impl.UserDao")) {
var10000.((UserDao)var2[0]);
break;
}
throw new IllegalArgumentException("Constructor not found");
default:
throw new IllegalArgumentException("Constructor not found");
}
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
InvocationHandler var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
default:
var10000 = null;
}
return var10000;
}
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (InvocationHandler)var2;
default:
}
}
public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0};
}
public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (InvocationHandler)var1[0];
}
static {
CGLIB$STATICHOOK1();
}
}
CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。但因为采用的是继承,所以不能对final修饰的类进行代理,要拦截的方法不能是final,static,private修饰。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。
通俗讲就是CGLib是通过生成代理类,并让它继承目标类,在对目标类中可以继承的方法做覆盖,并在该方法中做功能增强。由于多态关系,实则调用的还是子类的方法。
3、动态代理总结:
相对于静态代理,动态代理大大减少了我们的开发任务,同时减少了对业务的依赖,降低了耦合度,达到职责分离的效果。
动态代理使用倒是不难,但是,它里面涉及的一些设计原则还需要透彻理解,不过认真实现,阅读下动态代理对象的源码更能加深理解
站在前辈的肩膀上,每天进步一点点
ends~