java动态代理--proxy&cglib
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java动态代理--proxy&cglib,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4412字,纯文字阅读大概需要7分钟。
内容图文
![java动态代理--proxy&cglib](/upload/InfoBanner/zyjiaocheng/768/7e10eae68bae4c9bb8535474fd605198.jpg)
大纲
- 代理
- proxy
- cglib
- 小结
一、代理
为什么要用代理?其实就是希望不修改对象的情况下,增强对象。
静态代理:
- 静态代理模式,需要代理类和目标类实现同一接口,代理类的方法调用目标类的方法,调用方法的前后实现需要增强的逻辑。
- 静态代理有一个问题就是,每个代理类和目标类一一对应,需要代理的类多的情况,需要大量的代理类,难以维护。
动态代理:
- 动态代理就是运行时动态生成的类,并不是在编译时期。
- 动态代理有两种不同的方式,一种是jdk反射包下的的Prxoy,一种是cglib。
二、Proxy
Proxy生成代理对象需要目标对象实现一至少一个接口。
Proxy通过反射实现动态代理。
生成代理对象需要调用Proxy中newProxyInstance方法。
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
loader-目标对象的classloader
interfaces-目标对象实现的接口
InvocationHandler-处理器,当目标对象接口中的方法被调用时处理器中invoke方法会被调用从而实现动态代理
在看下InvocationHandler
public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }
proxy-代理对象
method-被调用的方法
args-调用方法时传入的参数
invoke返回值为代理方法的返回值
测试:
接口:
public interface Speak { String say(String content); }
目标类:
import lombok.Data;
@Data public class Person implements Speak{ private String name; private int age; public String say(String content){ System.out.println("hi"+name+age+"content:"+content); return "say return"; } }
代理工厂:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyFactory{ //维护一个目标对象 private Object target; public ProxyFactory(Object target) { this.target = target; } //生成代理对象 public Object getProxyInstance() { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before method:"+method.getName()); //执行目标对象方法,返回return值。 Object returnValue = method.invoke(target, args); System.out.println("end method:"+method.getName()); return returnValue; } }); } }
代理对象在代理方法调用前后打了一行字。
public static void main(String[] args) { Person p = new Person(); p.setAge(11); p.setName("xx"); ProxyFactory factory = new ProxyFactory(p); Object proxyInstance = factory.getProxyInstance(); Speak speak = (Speak) proxyInstance; String returnValue = speak.say("haha"); System.out.println("returnValue:"+returnValue); }
三、cglib
静态代理和都必须实现接口,而cglib没有这个限制,cglib通过字节码操作动态生成子类,因此目标类不能被final修饰。
与proxy类似的我们也需要复写一个处理器
public interface MethodInterceptor extends Callback { Object (Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable; }
proxy-代理对象
method-被调用的方法
methodProxy-代理方法(具体本人不是特别清楚)
intercept返回值为代理方法的返回值
测试:
重写Person不需要实现接口
import lombok.Data; @Data public class Person{ private String name; private int age; public String say(String content){ System.out.println("hi"+name+age+"content:"+content); return "say return"; } }
代理工厂:
import org.assertj.core.internal.cglib.proxy.Enhancer; import org.assertj.core.internal.cglib.proxy.MethodInterceptor; import org.assertj.core.internal.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CgProxyFactory<T> { //维护目标对象 private T target; public CgProxyFactory(T target) { this.target = target; } //获取代理 public T getProxyInstance() { Enhancer en = new Enhancer(); en.setSuperclass(this.target.getClass()); //设置拦截器 en.setCallback(new MethodInterceptor() { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("before method:"+method.getName()); Object returnValue = method.invoke(target, objects); System.out.println("end method:"+method.getName()); return returnValue; } }); return (T) en.create(); } }
和之前的代理对象一样,在代理方法调用前后打了一行字。
public static void main(String[] args) { Person p = new Person(); p.setAge(11); p.setName("xx"); CgProxyFactory<Person> factory = new CgProxyFactory(p); Person proxyInstance = factory.getProxyInstance(); String returnValue = proxyInstance.say("cg"); System.out.println("returnValue:" + returnValue); }
四、小结:
- Proxy需要代理类实现接口,底层为反射。
- Cglib代理对象不能被final修饰,底层是字节码操作。
- spring会根据目标类是否实现接口的情况,切换动态代理的模式,也可以通过配置强制使用cglib。
内容总结
以上是互联网集市为您收集整理的java动态代理--proxy&cglib全部内容,希望文章能够帮你解决java动态代理--proxy&cglib所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。