代理模式与AOP等

梦里梦外; 2023-10-05 12:44 51阅读 0赞

参考https://course.study.163.com/480000005493360/lecture-480000036686223

静态代理:

接口类:

  1. public interface GameFactory {
  2. public String make();
  3. }

委托类(被代理类):

  1. public class GameBoyFactory implements GameFactory {
  2. public String make() {
  3. return "GameBoy";
  4. }
  5. }
  6. public class Ps4Factory implements GameFactory {
  7. public String make() {
  8. return "ps4";
  9. }
  10. }

代理类:

  1. public class SdhProxy implements GameFactory{
  2. private GameFactory realFactory;
  3. public SdhProxy(GameFactory realFactory) {
  4. this.realFactory = realFactory;
  5. }
  6. public void setRealFactory(GameFactory realFactory) {
  7. this.realFactory = realFactory;
  8. }
  9. public String make() {
  10. pre();
  11. System.out.println(realFactory.make());
  12. post();
  13. return null;
  14. }
  15. private static void pre( ){
  16. System.out.println("pre");
  17. }
  18. private static void post( ){
  19. System.out.println("post");
  20. }
  21. }

调用者:

  1. public class Caller {
  2. public static void main(String[] args ){
  3. GameFactory proxy = new SdhProxy(new GameBoyFactory());
  4. proxy.make();
  5. ((SdhProxy) proxy).setRealFactory(new Ps4Factory());
  6. proxy.make();
  7. }
  8. }

输出:
pre
GameBoy
post
pre
ps4
post

动态代理:

代理类:

  1. public class SdhProxy2 implements InvocationHandler {
  2. Object target; //被代理对象
  3. public Object getTarget() {
  4. return target;
  5. }
  6. public void setTarget(Object target) {
  7. this.target = target;
  8. }
  9. public Object getProxy(){
  10. //生成代理对象
  11. return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
  12. }
  13. @Override
  14. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  15. long pre = pre();
  16. Object result = method.invoke(target, args);
  17. System.out.println(result);
  18. long post = post();
  19. return result+"--"+(post-pre);
  20. }
  21. private static long pre( ){
  22. return System.currentTimeMillis();
  23. }
  24. private static long post( ){
  25. return System.currentTimeMillis();
  26. }
  27. }

将调用者的执行代码改为:

  1. SdhProxy2 proxy2 = new SdhProxy2();
  2. GameFactory target = new GameBoyFactory();
  3. proxy2.setTarget(target);
  4. GameFactory pro = (GameFactory) proxy2.getProxy();
  5. System.out.println(pro.make());
  6. target = new Ps4Factory();
  7. proxy2.setTarget(target);
  8. System.out.println(pro.make());

输出:
GameBoy
GameBoy–0
ps4
ps4–0

  • 注意动态代理可以提供到方法级的代理。比如接口类增加了一个方法design(),而代理类并不想管这个方法。

    //接口类:
    public interface GameFactory {

    1. public String make();
    2. public String design();

    }

    //委托类(被代理类):
    public class GameBoyFactory implements GameFactory {

    1. public String make() {
    2. return "GameBoy";
    3. }
    4. public String design() {
    5. return null;
    6. }

    }

    public class Ps4Factory implements GameFactory {

    1. public String make() {
    2. return "ps4";
    3. }
    4. public String design() {
    5. return null;
    6. }

    }

代理类SdhProxy2与调用者Caller都不需做任何变更,输出结果也不变。而如果用的是静态代理SdhProxy,它将不得不实现其并不关心的design()方法。

一些相关问题:

比较于CGLIB动态代理,为什么JDK动态代理只能代理实现了接口的类?

其实也简单,看看被圈起来的代码:
在这里插入图片描述
可参考的分析文章1,2:生成的代理类继承了Proxy类,由于java是单继承,所以代理对象只能声明为接口。
我实操了一下,确实getProxy()返回的代理对象只能被转为接口类型,否则会报错。

JDK 动态代理中,被代理对象(目标对象)调用自己的另一个方法,会经过代理对象么?1

解答:被代理对象(目标对象)调用内部方法的是本身,被调用的方法不会经过代理对象。

" class="reference-link">一些其他相关例子3:在这里插入图片描述

RequestMapping可以生效,但是切面LoggedCheck不生效。为什么?
参考答案:AOP是基于JDK动态代理和CGLib,前者只能代理接口方法,所以不能代理static方法,后者也不支持代理static方法? 而@RequestMapping并不是AOP实现。

AOP只能增强public方法吗?

参见本博——-前海微众银行面经(部分) 的一面部分


  1. 面试必问系列之JDK动态代理 注:文中的将代理对象的class文件落盘的方法System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); 亲测无效。据https://blog.csdn.net/MrYushiwen/article/details/111473126,JDK1.8以后应该用System.setProperty("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");,亲测有效。 ↩︎ ↩︎
  2. java动态代理为什么需要基于接口 ↩︎
  3. B站极海Channel ↩︎

发表评论

表情:
评论列表 (有 0 条评论,51人围观)

还没有评论,来说两句吧...

相关阅读

    相关 AOP代理模式

    代理模式: 1.静态代理 原理:创建一个代理类实现目标类的接口,在代理类中包含目标类的对象 案例: 1)需要创建一个接口 public interface

    相关 AOP实现机制 - 代理模式

    AOP实现机制 - 代理模式 代理模式 (1)真是角色更加纯粹!不需要关心一些公共业务。 (2)公共业务也就交给了代理角色。 (3)公共业务大声扩展的时候,方便