-
动态代理示例
2018-09-11 17:43:06动态代理,它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy... -
java设计模式——动态代理示例
2021-01-06 22:34:04动态代理示例实现动态分库功能示例 1、代码结构如下图: 2、创建订单和用户类 package com.rf.designPatterns.structural.proxy; /** * @description: 订单和用户类 * @author: xz */ public class Order { ...动态代理示例实现动态分库功能示例
1、代码结构如下图:
2、创建订单和用户类
package com.rf.designPatterns.structural.proxy; /** * @description: 订单和用户类 * @author: xz */ public class Order { private Object orderId;//订单id private Integer userId;//用户id public Object getOrderId() { return orderId; } public void setOrderId(Object orderId) { this.orderId = orderId; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } }
3、创建Service层
package com.rf.designPatterns.structural.proxy; /** * @description: Service层 * @author: xz */ public interface OrderService { int saveOrder(Order order); }
4、创建Dao层
package com.rf.designPatterns.structural.proxy; /** * @description: Dao层 * @author: xz */ public interface OrderDao { int insert(Order order); }
5、创建Dao实现层
package com.rf.designPatterns.structural.proxy; /** * @description: Dao实现层 * @author: xz */ public class OrderDaoImpl implements OrderDao{ @Override public int insert(Order order) { System.out.println("Dao层添加订单成功"); return 1; } }
6、创建Service实现层
package com.rf.designPatterns.structural.proxy; /** * @description: Service实现层 * @author: xz */ public class OrderServiceImpl implements OrderService{ private OrderDao orderDao; @Override public int saveOrder(Order order) { //spring会自动注入,这里我们自己直接new orderDao=new OrderDaoImpl(); System.out.println("Service调用Dao层的inser方法添加订单"); orderDao.insert(order); return 1; } }
7、创建数据源上下文类
package com.rf.designPatterns.structural.proxy.db; /** * @description: 数据源上下文类 * @author: xz */ public class DataSourceContextHolder { private static final ThreadLocal<String> CONTEXT_HOLDER=new ThreadLocal<String>(); public static void setDBType(String dbType){ CONTEXT_HOLDER.set(dbType); } public static String getDBType(){ return CONTEXT_HOLDER.get(); } public static void clearDBType(){ CONTEXT_HOLDER.remove(); } }
8、创建动态的数据源类
package com.rf.designPatterns.structural.proxy.db; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /** * @description: 动态的数据源类 * @author: xz */ public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDBType(); } }
9、创建Service层的动态代理
package com.rf.designPatterns.structural.proxy.dynamicProxy; import com.rf.designPatterns.structural.proxy.Order; import com.rf.designPatterns.structural.proxy.db.DataSourceContextHolder; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @description: Service层的动态代理 * @author: xz */ public class OrderServiceDynamicProxy implements InvocationHandler { //声明一个目标对象 private Object target; //通过构造器添加目标对象 public OrderServiceDynamicProxy(Object target) { this.target = target; } //绑定目标对象 public Object bind(){ Class cls=target.getClass();//获取目标类的class对象 return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),this); } /** * @param proxy 动态生成的代理类 * @param method 要被增强的方法对象 * @param args method方法的参数 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object argObject = args[0]; beforeMethod(argObject); Object object = method.invoke(target, args); afterMethod(); return object; } private void beforeMethod(Object obj){ System.out.println("动态代理before代码, 在invoke方法之前执行"); int userId=0; if(obj instanceof Order){ Order order=(Order)obj; userId= order.getUserId(); } int dbRouter=userId % 2; System.out.println("动态代理分配到 db【" +dbRouter+ "】 数据库处理数据"); DataSourceContextHolder.setDBType("db"+String.valueOf(dbRouter)); } private void afterMethod(){ System.out.println("动态代理after代码, 在invoke方法之后执行"); } }
10、创建测试类
package com.rf.designPatterns.structural.proxy.dynamicProxy; import com.rf.designPatterns.structural.proxy.Order; import com.rf.designPatterns.structural.proxy.OrderService; import com.rf.designPatterns.structural.proxy.OrderServiceImpl; public class Test { public static void main(String[] args) { Order order=new Order(); //order.setUserId(1); order.setUserId(2); OrderService orderServiceDynamicProxy = (OrderService) new OrderServiceDynamicProxy(new OrderServiceImpl()).bind(); orderServiceDynamicProxy.saveOrder(order); } }
11、测试结果如下图:
-
CGLIB动态代理示例与源码解析
2018-09-18 21:03:50不细介绍,看我上一篇文章 JDK8动态代理示例与原码解析 1.1 动态代理模式步骤 生成代理类二进制字节码,可配置参数生成文件。 classloader load二进制字节码,生成Class对象( 可使用public static Class&...1. 原理,代理模式
代理模式的本质:调用方--->代理方--->实现方。
不细介绍,看我上一篇文章 JDK8动态代理示例与原码解析
1.1 动态代理模式步骤
生成代理类二进制字节码,可配置参数生成文件。
classloader load二进制字节码,生成Class对象( 可使用public static Class<?> forName(String className))
Class对象反射构造方法,构造方法newInstance创建对象
2. CGLib代理示例
pom.xml加入
<!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.5</version> </dependency>
public class HelloService { public void sayHello(String something) { System.out.println("hello, " + something); } } public class HelloCGLibProxy implements MethodInterceptor { public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("-----------"+method.getName()+"-------"); return methodProxy.invokeSuper(o, objects); } } public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(HelloService.class); enhancer.setCallback(new HelloCGLibProxy()); Object obj = enhancer.create(); HelloService helloService = (HelloService) obj; helloService.sayHello("ok"); } -----------sayHello------- hello, ok
3. 源码分析
核心方法
enhancer.create()
看注释一目了然,Generate a new class if necessary
/** * Generate a new class if necessary and uses the specified * callbacks (if any) to create a new object instance. * Uses the no-arg constructor of the superclass. * @return a new instance */ public Object create() { classOnly = false; argumentTypes = null; return createHelper(); }
createHelper()
private static final EnhancerKey KEY_FACTORY = (EnhancerKey)KeyFactory.create(EnhancerKey.class, KeyFactory.HASH_ASM_TYPE, null); public interface EnhancerKey { public Object newInstance(String type, String[] interfaces, WeakCacheKey<CallbackFilter> filter, Type[] callbackTypes, boolean useFactory, boolean interceptDuringConstruction, Long serialVersionUID); } private Object createHelper() { //验证 preValidate(); //生成key,EnhancerKey KEY_FACTORY初始化的时候,通过CGLIB动态生成实现类 //先自己CGLIB给自己动态创建实现类了 Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null, ReflectUtils.getNames(interfaces), filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter), callbackTypes, useFactory, interceptDuringConstruction, serialVersionUID); this.currentKey = key; //父类使用EnhancerKey创建对象 Object result = super.create(key); return result; }
调试看图,传入了代理的类对象和方法拦截器(CGLIB的核心思想)
3.1 创建KeyFactory对象,此处居然就使用了CGLIB动态代理技术,下面逐一分析。
KeyFactory.create(EnhancerKey.class, KeyFactory.HASH_ASM_TYPE, null) //动态创建EnhancerKey实现类
public static KeyFactory create(ClassLoader loader, Class keyInterface, KeyFactoryCustomizer customizer, List<KeyFactoryCustomizer> next) { Generator gen = new Generator(); gen.setInterface(keyInterface); if (customizer != null) { gen.addCustomizer(customizer); } if (next != null && !next.isEmpty()) { for (KeyFactoryCustomizer keyFactoryCustomizer : next) { gen.addCustomizer(keyFactoryCustomizer); } } gen.setClassLoader(loader); return gen.create(); } public KeyFactory create() { setNamePrefix(keyInterface.getName()); return (KeyFactory)super.create(keyInterface.getName()); }
super.create(keyInterface.getName()
使用WeakHashMap缓存,以classLoader为key,value是ClassLoaderData
private static volatile Map<ClassLoader, ClassLoaderData> CACHE = new WeakHashMap<ClassLoader, ClassLoaderData>(); protected Object create(Object key) { try { ClassLoader loader = getClassLoader(); Map<ClassLoader, ClassLoaderData> cache = CACHE; ClassLoaderData data = cache.get(loader); if (data == null) { synchronized (AbstractClassGenerator.class) { cache = CACHE; data = cache.get(loader); if (data == null) { Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache); data = new ClassLoaderData(loader); newCache.put(loader, data); CACHE = newCache; } } } this.key = key; Object obj = data.get(this, getUseCache()); if (obj instanceof Class) { return firstInstance((Class) obj); } return nextInstance(obj); } catch (RuntimeException e) { throw e; } catch (Error e) { throw e; } catch (Exception e) { throw new CodeGenerationException(e); } }
我们看new ClassLoaderData()发生了什么
public ClassLoaderData(ClassLoader classLoader) { if (classLoader == null) { throw new IllegalArgumentException("classLoader == null is not yet supported"); } this.classLoader = new WeakReference<ClassLoader>(classLoader); Function<AbstractClassGenerator, Object> load = new Function<AbstractClassGenerator, Object>() { public Object apply(AbstractClassGenerator gen) { //此处生成字节码 Class klass = gen.generate(ClassLoaderData.this); return gen.wrapCachedClass(klass); } }; generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load); }
Class klass = gen.generate(ClassLoaderData.this);
protected Class generate(ClassLoaderData data) { Class gen; Object save = CURRENT.get(); CURRENT.set(this); try { ClassLoader classLoader = data.getClassLoader(); if (classLoader == null) { throw new IllegalStateException("ClassLoader is null while trying to define class " + getClassName() + ". It seems that the loader has been expired from a weak reference somehow. " + "Please file an issue at cglib's issue tracker."); } synchronized (classLoader) { //动态代理生成类名称 String name = generateClassName(data.getUniqueNamePredicate()); data.reserveName(name); this.setClassName(name); } //有代理类直接加载 if (attemptLoad) { try { gen = classLoader.loadClass(getClassName()); return gen; } catch (ClassNotFoundException e) { // ignore } } //生成字节码 byte[] b = strategy.generate(this); String className = ClassNameReader.getClassName(new ClassReader(b)); ProtectionDomain protectionDomain = getProtectionDomain(); synchronized (classLoader) { // just in case //加载类,生成class对象 if (protectionDomain == null) { gen = ReflectUtils.defineClass(className, b, classLoader); } else { gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain); } } return gen; } catch (RuntimeException e) { throw e; } catch (Error e) { throw e; } catch (Exception e) { throw new CodeGenerationException(e); } finally { CURRENT.set(save); } }
类名生成规则,使用$和$$加哈希值,跟上面调试的代码一致。
public String getClassName(String prefix, String source, Object key, Predicate names) { if (prefix == null) { prefix = "net.sf.cglib.empty.Object"; } else if (prefix.startsWith("java")) { prefix = "$" + prefix; } String base = prefix + "$$" + source.substring(source.lastIndexOf('.') + 1) + getTag() + "$$" + Integer.toHexString(STRESS_HASH_CODE ? 0 : key.hashCode()); String attempt = base; int index = 2; while (names.evaluate(attempt)) attempt = base + "_" + index++; return attempt; }
下面看字节码生成类
public byte[] generate(ClassGenerator cg) throws Exception { DebuggingClassWriter cw = getClassVisitor(); transform(cg).generateClass(cw); return transform(cw.toByteArray()); } public class DebuggingClassWriter extends ClassVisitor { public static final String DEBUG_LOCATION_PROPERTY = "cglib.debugLocation"; //这里可以设置写文件的位置 private static String debugLocation = System.getProperty("cglib.debugLocation"); private static Constructor traceCtor; private String className; private String superName; public DebuggingClassWriter(int flags) { super(327680, new ClassWriter(flags)); } public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { this.className = name.replace('/', '.'); this.superName = superName.replace('/', '.'); super.visit(version, access, name, signature, superName, interfaces); } public String getClassName() { return this.className; } public String getSuperName() { return this.superName; } public byte[] toByteArray() { return (byte[])((byte[])AccessController.doPrivileged(new PrivilegedAction() { public Object run() { byte[] b = ((ClassWriter)DebuggingClassWriter.access$001(DebuggingClassWriter.this)).toByteArray(); //如果有文件位置则写文件 if (DebuggingClassWriter.debugLocation != null) { String dirs = DebuggingClassWriter.this.className.replace('.', File.separatorChar); try { (new File(DebuggingClassWriter.debugLocation + File.separatorChar + dirs)).getParentFile().mkdirs(); File file = new File(new File(DebuggingClassWriter.debugLocation), dirs + ".class"); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file)); try { out.write(b); } finally { out.close(); } if (DebuggingClassWriter.traceCtor != null) { file = new File(new File(DebuggingClassWriter.debugLocation), dirs + ".asm"); out = new BufferedOutputStream(new FileOutputStream(file)); try { ClassReader cr = new ClassReader(b); PrintWriter pw = new PrintWriter(new OutputStreamWriter(out)); ClassVisitor tcv = (ClassVisitor)DebuggingClassWriter.traceCtor.newInstance(null, pw); cr.accept(tcv, 0); pw.flush(); } finally { out.close(); } } } catch (Exception var17) { throw new CodeGenerationException(var17); } } return b; } })); }
可以通过
System.getProperty("cglib.debugLocation")
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/home/xxx");
通过设置可以写文件,写道指定的路径。
此处 通过写字节码的方式实现了EnhancerKey子类,实现相关功能。这里没有注册方法拦截器,因为是自己实现接口的实现类。
public void generateClass(ClassVisitor v) { //继承父类EnhancerKey ClassEmitter ce = new ClassEmitter(v); Method newInstance = ReflectUtils.findNewInstance(keyInterface); if (!newInstance.getReturnType().equals(Object.class)) { throw new IllegalArgumentException("newInstance method must return Object"); } Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes()); //继承实现 ce.begin_class(Constants.V1_2, Constants.ACC_PUBLIC, getClassName(), KEY_FACTORY, new Type[]{ Type.getType(keyInterface) }, Constants.SOURCE_FILE); EmitUtils.null_constructor(ce); EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance)); int seed = 0; CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, TypeUtils.parseConstructor(parameterTypes), null); e.load_this(); e.super_invoke_constructor(); e.load_this(); //属性 List<FieldTypeCustomizer> fieldTypeCustomizers = getCustomizers(FieldTypeCustomizer.class); for (int i = 0; i < parameterTypes.length; i++) { Type parameterType = parameterTypes[i]; Type fieldType = parameterType; for (FieldTypeCustomizer customizer : fieldTypeCustomizers) { fieldType = customizer.getOutType(i, fieldType); } seed += fieldType.hashCode(); ce.declare_field(Constants.ACC_PRIVATE | Constants.ACC_FINAL, getFieldName(i), fieldType, null); e.dup(); e.load_arg(i); for (FieldTypeCustomizer customizer : fieldTypeCustomizers) { customizer.customize(e, i, parameterType); } e.putfield(getFieldName(i)); } e.return_value(); e.end_method(); // hash code //方法 e = ce.begin_method(Constants.ACC_PUBLIC, HASH_CODE, null); int hc = (constant != 0) ? constant : PRIMES[(int)(Math.abs(seed) % PRIMES.length)]; int hm = (multiplier != 0) ? multiplier : PRIMES[(int)(Math.abs(seed * 13) % PRIMES.length)]; e.push(hc); for (int i = 0; i < parameterTypes.length; i++) { e.load_this(); e.getfield(getFieldName(i)); EmitUtils.hash_code(e, parameterTypes[i], hm, customizers); } e.return_value(); e.end_method(); // equals e = ce.begin_method(Constants.ACC_PUBLIC, EQUALS, null); Label fail = e.make_label(); e.load_arg(0); e.instance_of_this(); e.if_jump(e.EQ, fail); for (int i = 0; i < parameterTypes.length; i++) { e.load_this(); e.getfield(getFieldName(i)); e.load_arg(0); e.checkcast_this(); e.getfield(getFieldName(i)); EmitUtils.not_equals(e, parameterTypes[i], fail, customizers); } e.push(1); e.return_value(); e.mark(fail); e.push(0); e.return_value(); e.end_method(); // toString e = ce.begin_method(Constants.ACC_PUBLIC, TO_STRING, null); e.new_instance(Constants.TYPE_STRING_BUFFER); e.dup(); e.invoke_constructor(Constants.TYPE_STRING_BUFFER); for (int i = 0; i < parameterTypes.length; i++) { if (i > 0) { e.push(", "); e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING); } e.load_this(); e.getfield(getFieldName(i)); EmitUtils.append_string(e, parameterTypes[i], EmitUtils.DEFAULT_DELIMITERS, customizers); } e.invoke_virtual(Constants.TYPE_STRING_BUFFER, TO_STRING); e.return_value(); e.end_method(); ce.end_class(); }
3.2 示例的动态代理。
上面介绍了KeyFactory使用CGLIB的源码,下面是我们自己写的类实现动态代理
Object result = super.create(key)//key就是上面CGLIB动态创建的KeyFactory对象。
原理跟KeyFactory一样,只是generateClass实现不一样
核心:注册了方法拦截器,就是我们示例里面
public class HelloCGLibProxy implements MethodInterceptor
public void generateClass(ClassVisitor v) throws Exception { Class sc = (superclass == null) ? Object.class : superclass; //final 类不能代理,因为CGLIB是通过继承实现子类的方式达到动态代理的目的 if (TypeUtils.isFinal(sc.getModifiers())) throw new IllegalArgumentException("Cannot subclass final class " + sc.getName()); //已定义的构造器 List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors())); //剔除相同的构造器 filterConstructors(sc, constructors); // Order is very important: must add superclass, then // its superclass chain, then each interface and // its superinterfaces. List actualMethods = new ArrayList(); List interfaceMethods = new ArrayList(); final Set forcePublic = new HashSet(); getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic); List methods = CollectionUtils.transform(actualMethods, new Transformer() { public Object transform(Object value) { Method method = (Method)value; int modifiers = Constants.ACC_FINAL | (method.getModifiers() & ~Constants.ACC_ABSTRACT & ~Constants.ACC_NATIVE & ~Constants.ACC_SYNCHRONIZED); if (forcePublic.contains(MethodWrapper.create(method))) { modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC; } return ReflectUtils.getMethodInfo(method, modifiers); } }); //设置父类 ClassEmitter e = new ClassEmitter(v); //写继承实现关系 if (currentData == null) { e.begin_class(Constants.V1_2, Constants.ACC_PUBLIC, getClassName(), Type.getType(sc), (useFactory ? TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) : TypeUtils.getTypes(interfaces)), Constants.SOURCE_FILE); } else { e.begin_class(Constants.V1_2, Constants.ACC_PUBLIC, getClassName(), null, new Type[]{FACTORY}, Constants.SOURCE_FILE); } List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance()); //属性 e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null); e.declare_field(Constants.ACC_PUBLIC | Constants.ACC_STATIC, FACTORY_DATA_FIELD, OBJECT_TYPE, null); if (!interceptDuringConstruction) { e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null); } e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null); e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null); if (serialVersionUID != null) { e.declare_field(Constants.PRIVATE_FINAL_STATIC, Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID); } for (int i = 0; i < callbackTypes.length; i++) { e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null); } // This is declared private to avoid "public field" pollution e.declare_field(Constants.ACC_PRIVATE | Constants.ACC_STATIC, CALLBACK_FILTER_FIELD, OBJECT_TYPE, null); //定义方法 if (currentData == null) { emitMethods(e, methods, actualMethods); emitConstructors(e, constructorInfo); } else { emitDefaultConstructor(e); } //定义方法拦截器,CGLIB动态代理功能依赖于方法拦截器实现 emitSetThreadCallbacks(e); emitSetStaticCallbacks(e); emitBindCallbacks(e); if (useFactory || currentData != null) { int[] keys = getCallbackKeys(); emitNewInstanceCallbacks(e); emitNewInstanceCallback(e); emitNewInstanceMultiarg(e, constructorInfo); emitGetCallback(e, keys); emitSetCallback(e, keys); emitGetCallbacks(e); emitSetCallbacks(e); } e.end_class(); }
调试结果如下:
可以看出是Enhancer中生成了HelloService的代理类,此类事HelloService的子类。
4. 反编译代理类
设置属性
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "xxx");
有三个文件,中间那个就是我们的代理类
通过继承的方式来实现代理的
优点:可以代理类,代理速度快
缺点:不能代理final类final方法,生成字节码很慢,生成3个类
-
Java动态代理示例代码.rar
2020-05-19 15:47:11使用java完成动态代理的演示代码,适合初学者理解动态代理的功能,进行参考,本代码是简单的demo代码,仅用于学习参考。 -
Java spring AOP(面向切面编程) JDK动态代理示例
2019-10-21 14:05:34Java spring AOP面向切面编程JDK动态代理示例Java spring AOP(面向切面编程) JDK动态代理示例目标类目标类接口目标类实现切面类spring工厂测试 Java spring AOP(面向切面编程) JDK动态代理示例 本文引用B站老师(...Java spring AOP(面向切面编程) JDK动态代理示例
本文引用B站老师(“一个体面的人”发布的视频) spring框架教程相关内容,适合初学者理解使用
了解更多内容点击链接.AOP概念:
(百度百科)
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
JDK动态代理,可简单的理解为将advice(增强)和到target(目标类)织入代理中,在每次执行目标类方法时,都会动态的执行对应的增强方法。在本示例中,即将切面类的before方法和after方法,通过spring工厂中的代理proxService,加到每个目标方法前、后执行。目标类
目标类接口
文件名:UserService.java
package com.itheima.a_proxy.a_jdk; /*目标类接口*/ public interface UserService { public void addUser(); public void updateUser(); public void deleteUser(); }
目标类实现
文件名:UserServiceImpl.java
package com.itheima.a_proxy.a_jdk; /*目标类实现*/ public class UserServiceImpl implements UserService { @Override public void addUser(){ System.out.println("a_proxy.a_jdk addUser"); } @Override public void updateUser(){ System.out.println("a_proxy.a_jdk updateUser"); } @Override public void deleteUser(){ System.out.println("a_proxy.a_jdk deleteUser"); } }
切面类
切面类含有before方法和after方法
文件名:MyAspect.javapackage com.itheima.a_proxy.a_jdk; /*切面类*/ public class MyAspect { public void before(){ System.out.println("前方法"); } public void after(){ System.out.println("后方法"); } }
spring工厂
文件名:MyBeanFactory.java
package com.itheima.a_proxy.a_jdk; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MyBeanFactory { public static UserService createService(){ //return new UserServiceImpl(); //1.目标类,匿名类前加final final UserService userService = new UserServiceImpl(); //2.切面类 final MyAspect myAspect = new MyAspect(); /*3.代理类:将目标类(切入点)和切面类(通知)结合,即切面 *Proxy.newProxyInstance(loader,interfaces,h) * 参数1:loader,类加载器,动态代理类运行时创建,任何类都需要类加载器将其加载到内存。 * 一般情况:当前类.class.getClassLoader(); * 目标类实例.getClass.get... * 参数2:interfaces,代理类需要实现的所有接口 * 方式1:目标类实例.getClass().getInterfaces();注意,只能获得自己的接口,不能获得父类元素的接口 * 方式2:new Class[]{UserService.class} 例如:jsbc驱动 DriverManager 获得接口Connection * 参数3:InvocationHandler 处理类,接口,必须进行实现类,一般采用匿名内部 * 提供invoke(Object proxy, Method method, Object[] args)方法:代理类的每一个方法执行时,都将调用一次invoke * 参数(1)Object proxy:代理对象 * 参数(2)Method method:代理对象当前执行的方法的描述对象(反射) * 执行方法名获得:method.getName() * 执行方法:method.invoke(对象,实际参数) * 参数(3)Object[] args:方法实际参数 * */ UserService proxService = (UserService) Proxy.newProxyInstance( MyBeanFactory.class.getClassLoader(), userService.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //将目标类和切面类结合 //前执行 myAspect.before(); //执行目标方法 Object obj = method.invoke(userService,args); //后执行 myAspect.after(); return obj; } }); return proxService; } }
测试
文件名:TestJDK.java
package com.itheima.a_proxy.a_jdk; import org.junit.Test; import org.springframework.test.context.TestExecutionListeners; public class TestJDK { @Test public void demo01(){ UserService userService = MyBeanFactory.createService(); userService.addUser(); userService.updateUser(); userService.deleteUser(); } }
测试执行结果
-
《秒回面试官》下次面试官再问你动态代理,这样回他!附java动态代理示例代码
2021-02-05 17:12:05附java动态代理示例代码 java动态代理的两种方式 jdk自带的动态代理 只能代理实现了接口的类,实现InvocationHandler接口的invoke()方法。 cglib包动态代理 针对类实现代理,原理是通过目标类生成一个子类...面试官:java动态代理了解吧,能说说有哪几种实现方式啊?有什么区别啊?
不废话,秒回答案!就是这么拽~
第一种:基于jdk自带的动态代理
只能代理实现了接口的类,实现 InvocationHandler 接口的 invoke() 方法。
由于代理的是接口,所以方法的访问修饰符一定是 public ,否则代理不了啊!这也是为什么 Spring 的 @Transactional 注解只能作用于 public 方法上。
第二种:基于cglib包动态代理
针对类实现代理,原理是通过目标类生成一个子类,并覆盖方法实现增强,通过实现 MethodInterceptor 接口,getInstance() 方法用于生成一个子类,intercept() 方法进行拦截。
基于此方式需要依赖 cglib 包:
<dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>2.1_3</version> </dependency>
动态代理应用场景
动态代理在 Java 中有着广泛的应用,比如 AOP 切面、RPC远程调用、Java 注解对象获取、日志框架、全局性异常处理、申明式事务@Transactional 等。
java动态代理示例代码下载
https://github.com/yushouling/dynamic_proxy
# java动态代理的两种实现方式
- END -
-
静态代理和动态代理示例
2020-04-14 00:29:21代理模式主要有两种:静态代理和动态代理 **1,静态代理:** 比如要在输出“HelloWorld”前打印一个字符串“Welcome” A:先定义一个接口类 public interface HelloWorldIF { public void print(); // public ... -
Java JDK动态代理示例
2019-03-24 12:37:451. JDK动态代理原理 JDK动态代理是java.lang.reflect.*包提供的方式,必须借助接口才能产生代理对象。 在JDK动态代理中,要实现代理逻辑类必须实现java.lang.reflect.InvocationHandler接口,里面定义了invoke方法,... -
Java CGLIB动态代理示例
2019-03-24 12:39:221. CGLIB动态代理简介 JDK动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。 而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码... -
JDK动态代理示例
2016-04-29 21:08:02Java动态代理可以动态地创建代理并动态地处理对所代理方法的调用。下面用《Java编程思想》中的一个例子说明: 首先是接口类,目标类要实现的接口:public interface Interface { void doSomething(); void ... -
java 动态代理示例
2019-04-28 11:51:57package ... import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java... -
cglib动态代理示例
2018-11-08 14:08:192、代码示例 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 MyInterceptor ... -
cglib代理与jdk动态代理示例
2018-03-26 14:19:00先看基于jdk实现的动态代理实现例子 1、先声明一个接口类 1 public interface UserService{ 2 3 public String getName(String msg); 4 } 2、实现上面定义的接口类 1 public class UserServiceImpl ... -
Java 静态代理和动态代理 示例
2019-04-12 18:11:17只是自己学习时写的程序,只作为记录用,不是很...静态代理: 接口: package StaticProxy; public interface IPerson { void say(); } 实现类: package StaticProxy; public class Man implements IPerson ... -
java中的动态代理示例-基于接口的代理
2020-01-08 16:51:04示例中三个文件 一个接口,一个接口的实现类,一个客户端的模拟类,使用动态代理实现方法调用 //接口 public interface IProduct { String saleProduct(float money); String AfterSaleProduct(flo... -
java CGLIB 动态代理示例
2019-04-18 19:56:33import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy... import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method;...i... -
Java实现动态代理示例
2018-08-15 10:38:16首先定义一个接口 ...本文中的动态代理是通过JDK动态代理机制实现的,必须要先实现业务接口,即IStar接口;然后根据反射机制找到对应的被代理的类,就可以在动态生成的代理类中调用业务实现类的同名方法。 -
java之动态代理示例与底层原理
2020-07-21 09:36:04动态代理的意义在于生成一个占位(又称代理对象),来代理真实的对象,从而控制真实对象的访问 、 JDK动态代理 定义接口 1 2 3 public interface HelloWorld { public void ... -
JDK8动态代理示例与原码解析
2018-09-17 21:15:251. 原理,代理模式 代理模式的本质:调用方--->代理方--->实现方。 相对于:调用方---&...实现方,降低了调用方与实现方的藕联性,由代理方对...其中动态代理常用于Spring的AOP中,有JDK动态代理... -
JDK1.8动态代理示例及代理实现原理详解
2018-07-02 14:45:42一个简单的动态代理实现://目标对象需要实现的接口package reflection.DynamicProxy; public interface UserDao { void findUserByUserCode(String userCode); void findUserByEmai(String email); }//目标对象... -
jdk动态代理示例以及代码原理分析
2016-12-09 14:49:21相信很多人在刚刚学习Java时,会感觉【动态代理】晦涩难懂,只知道如何来调用它,却不知道它的实现细节。本文通过根据JDK源码,展示这些细节,以期能对JDK的动态代理有深入的理解。 简单示例代码 public class Proxy... -
java动态代理示例,自己实现Aop
2015-12-25 22:30:39这次的博客将会介绍两种动态代理的方式,一种为jdk动态代理,一种为cglib动态代理,在代码方面将会使用最少的代码来完成,类会尽量的少,帮助大家理解。 先讲一下这两种代理方式的主要区别,jdk动态代理要求... -
CGLIB子类代理和JDK动态代理示例和比较
2017-11-06 12:59:00JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用CGLIB实现。 CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java... -
Jdk提供的动态代理示例
2015-07-09 23:25:00* JDK动态代理示例 */ public class JDKDynamicProxyDemo { public static void main(String[] args) { Business business = new BusinessImpl(); Business proxy = (Business)Proxy.... -
java简单的动态代理示例
2015-07-07 14:11:481、定义一个接口Student,后面用于强转proxy实例类型 interface Student { public void study(); } 2、定义接口实现类StudentImpl ... 对象调用getClass().getClassLoader(), getClass().getInterfaces(),用于...
-
Android :提取字符串当中的数字
-
Unity 热更新技术-ILRuntime
-
android视频教程!微信小程序的事件处理,已拿到offer
-
Rails with vue js和tailwind-源码
-
day18面向对象续
-
MySQL你该了解的那些事【服务端篇】
-
Cakebrew:使用Cakebrew通过样式管理您的Homebrew公式-源码
-
vue3从0到1-超详细
-
Python启蒙到架构师的核心技术精讲课程
-
Open3D 从索引中提取点云
-
my_first_repo:尝试使用git并运行python脚本-源码
-
基于正交试验设计的测试用例选择方法
-
容器方式下的轻量仓库与CI 使用方案:Gitea + Drone 基础篇
-
2021-02-25
-
C语言
-
项目管理工具与方法
-
Unity ILRuntime框架设计
-
用于需求和供应的过程代数证明系统
-
static修饰的方法
-
benadamstyles:个人网站-源码