代理模式

举报
小鲍侃java 发表于 2021/09/10 23:34:49 2021/09/10
【摘要】 概念:委托一个代理类对另一个类进行控制(代理类中有被代理类的对象,同时可以在代理类中增强) 使用场景:aop(可以控制被代理类是否被调用,是否被代理)。 优点:1.确保被代理类的隐秘性            2.降低耦合性(不用挨个加需要增强的方法) 缺点:类数量的增多...

概念:委托一个代理类对另一个类进行控制(代理类中有被代理类的对象,同时可以在代理类中增强)

使用场景:aop(可以控制被代理类是否被调用,是否被代理)。

优点:1.确保被代理类的隐秘性

           2.降低耦合性(不用挨个加需要增强的方法)

缺点:类数量的增多,结构更复杂。

类图:

代码:

静态代理

1 静态代理:静态代理就是把增强的方法写在代理的类中,在编译时就确定了,这样耦合性比较高,除了方法量级较小或者增强的方法固定,其他情况不推荐。

subject接口


  
  1. public interface PlayLol{
  2. public void plya();
  3. }

realSubject


  
  1. public class IsPlay implements PlayLol{
  2. public void play() {
  3. System.out.println("开始玩");
  4. }
  5. }

proxy


  
  1. public class ProxySubject implements PlayLol{
  2. private PlayLol playLol;
  3. //关键,将被代理对象传进来
  4. public ProxySubject(final PlayLol playLol) {
  5. this.playLol = playLol;
  6. }
  7. public void play() {
  8. System.out.println("打开电脑");
  9. //可以增加控制 ,可以不让他玩。。。
  10. subject.play();
  11. System.out.println("15投");
  12. }
  13. }

调用


  
  1. public class MainClass {
  2. public static void main(String[] args) {
  3. PlayLol playLol = new IsPlay();
  4. playLol.paly();
  5. System.out.println("============");
  6. ProxySubject proxySubject = new ProxySubject(playLol);
  7. proxySubject.paly();
  8. }
  9. }


2.动态代理:

JDK代理

代理类


  
  1. public class ProxyHandler implements InvocationHandler {
  2. private Object object;
  3. public DynamicProxyHandler(final Object object) {
  4. this.object = object;
  5. }
  6. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  7. System.out.println("先开电脑");
  8. Object result = method.invoke(object, args);
  9. System.out.println("关电脑");
  10. return result;
  11. }
  12. }

调用:


  
  1. public class MainClass {
  2. public static void main(String[] args) {
  3. PlayLol subject = new IsPlay();
  4. /**
  5. * ClassLoader loader:指定当前目标对象使用的类加载器,获取加载器的方法是固定的
  6. * Class<?>[] interfaces:指定目标对象实现的接口的类型,使用泛型方式确认类型
  7. * InvocationHandler:指定动态处理器,执行目标对象的方法时,会触发事件处理器的方法
  8. * 都是固定写法
  9. */
  10. PlayLol proxySubject = (PlayLol) Proxy.newProxyInstance(PlayLol.class.getClassLoader(),
  11. new Class[]{PlayLol.class},
  12. new ProxyHandler(subject));
  13. proxySubject.play();
  14. }

CGLib动态代理

如果被代理类没有接口不可以使用jdk动态代理

代码:

被代理类


  
  1. public class IsPlay{
  2. public void play() {
  3. System.out.println("开始玩");
  4. }
  5. }

代理类


  
  1. public class CglibProxy implements MethodInterceptor {
  2. private Object target;//业务类对象,供代理方法中进行真正的业务方法调用
  3. //相当于JDK动态代理中的绑定
  4. public Object getInstance(Object target) {
  5. this.target = target; //给业务对象赋值
  6. Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类
  7. enhancer.setSuperclass(this.target.getClass()); //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
  8. //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
  9. enhancer.setCallback(this);
  10. // 创建动态代理类对象并返回
  11. return enhancer.create();
  12. // 以上都是固定写反
  13. }
  14. // 实现回调方法
  15. public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
  16. System.out.println("开电脑");
  17. proxy.invokeSuper(obj, args); //调用业务类(父类中)的方法
  18. System.out.println("关电脑");
  19. return null;
  20. }
  21. }

调用


  
  1. public class MainClass {
  2. public static void main(String[] args) {
  3. IsPlay play= new IsPlay();
  4. CglibProxy cglibProxy = new CglibProxy();
  5. IsPlay realSubjectProxy =
  6. (IsPlay) cglibProxy.getInstance(play);
  7. realSubjectProxy.play();
  8. }
  9. }

引用:CGLIB创建的动态代理对象比JDK创建的动态代理对象的性能更高,但是CGLIB创建代理对象时所花费的时间却比JDK多得多。所以对于单例的对象,因为无需频繁创建对象,用CGLIB合适,反之使用JDK方式要更为合适一些。同时由于CGLib由于是采用动态创建子类的方法,对于final修饰的方法无法进行代理。
 

文章来源: baocl.blog.csdn.net,作者:小黄鸡1992,版权归原作者所有,如需转载,请联系作者。

原文链接:baocl.blog.csdn.net/article/details/102546365

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。