万脑网站建设,工程管理咨询公司,苏州工业园区劳动局网站做不了合同,做网站的一般多钱分享一波:程序员赚外快-必看的巅峰干货
概念
通过代理控制对象的访问,可以详细访问某个对象的方法#xff0c;在这个方法调用处理#xff0c;或调用后处理#xff08;类似于AOP#xff09;。
代理设计模式应用场景#xff1a;AOP、权限控制、事务
常见代理的分类有在这个方法调用处理或调用后处理类似于AOP。
代理设计模式应用场景AOP、权限控制、事务
常见代理的分类有静态代理动态代理JDK动态代理Cglib等
注意本文所指的“代理”为设计模式中的“代理设计模式”跟正向、反向代理并非一个概念不要混淆。 静态代理
由程序员创建或工具生成代理类的源码再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件代理类和委托类的关系在运行前就确定了。
public interface IUserDao { void save(); }
public class UserDao implements IUserDao { public void save() { System.out.println(“已经保存数据…”); } }
/** 代理类 */ public class UserDaoProxy implements IUserDao { private IUserDao target; public UserDaoProxy(IUserDao iuserDao) { this.target iuserDao; } public void save() { System.out.println(“开启事物…”); target.save(); System.out.println(“关闭事物…”); }
}
静态代理需要每个被代理类都有一个代理类因此代码量较多实际开发中非必须情况尽量少用。 动态代理 JDK动态代理
1)原理是根据类加载器和接口创建代理类此代理类是接口的实现类所以必须使用接口 面向接口生成代理位于java.lang.reflect包下
2)实现方式 通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler new InvocationHandlerImpl(…); 通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类Class clazz Proxy.getProxyClass(classLoader,new Class[]{…}); 通过反射机制获取动态代理类的构造函数其参数类型是调用处理器接口类型Constructor constructor clazz.getConstructor(new Class[]{InvocationHandler.class}); 通过构造函数创建代理类实例此时需将调用处理器对象作为参数被传入Interface Proxy (Interface)constructor.newInstance(new Object[] (handler));
缺点jdk动态代理必须是面向接口目标业务类必须实现接口
public class InvocationHandlerImpl implements InvocationHandler {
/** 目标代理对象 */
private Object target;public InvocationHandlerImpl(Object target) {this.target target;
}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 反射执行方法Object invoke method.invoke(target, args);return invoke;
}
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException,IllegalAccessException, IllegalArgumentException, InvocationTargetException {// 被代理对象IUserDao userDao new UserDao();InvocationHandlerImpl invocationHandlerImpl new InvocationHandlerImpl(userDao);ClassLoader loader userDao.getClass().getClassLoader();Class?[] interfaces userDao.getClass().getInterfaces();// 主要装载器、一组接口及调用处理动态代理实例IUserDao newProxyInstance (IUserDao) Proxy.newProxyInstance(loader, interfaces, invocationHandlerImpl);newProxyInstance.save();
}}
Cglib动态代理
原理利用asm开源包对代理对象类的class文件加载进来通过修改其字节码生成子类来处理。
使用cglib[Code Generation Library]实现动态代理并不要求委托类必须实现接口底层采用asm字节码生成框架生成代理类的字节码
引入依赖 org.apache.commons commons-lang3 3.8.1 cglib cglib 3.1
创建代理
public class CglibProxy implements MethodInterceptor {
/** 代理对象 */
private Object target;public Object getInstance(Object target) {// 固定代码创建访问对象this.target target;Enhancer enhancer new Enhancer();enhancer.setSuperclass(target.getClass());enhancer.setCallback(this);return enhancer.create();
}public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object invoke methodProxy.invoke(target, args);return invoke;
}public static void main(String[] args) {CglibProxy cglibProxy new CglibProxy();UserDao userDao (UserDao) cglibProxy.getInstance(new UserDao());userDao.save();
}}
Cglib和jdk动态代理的区别
java动态代理是利用反射机制生成一个实现代理接口的匿名类在调用具体方法前调用InvokeHandler来处理。
而cglib动态代理是利用asm开源包对代理对象类的class文件加载进来通过修改其字节码生成子类来处理。
Spring中。
1、如果目标对象实现了接口默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口必须采用CGLIB库spring会自动在JDK动态代理和CGLIB之间转换
JDK动态代理只能对实现了接口的类生成代理而不能针对类 。
CGLIB是针对类实现代理主要是对指定的类生成一个子类覆盖其中的方法 。
因为是继承所以该类或方法最好不要声明成final final可以阻止继承和多态。
分享一波:程序员赚外快-必看的巅峰干货
如果以上内容对你觉得有用,并想获取更多的赚钱方式和免费的技术教程
请关注微信公众号:HB荷包 一个能让你学习技术和赚钱方法的公众号,持续更新