静态代理

Posted penguin1024

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了静态代理相关的知识,希望对你有一定的参考价值。

 


 

 静态代理的实现

 

1-3步,同上。

4. 创建 代理类   com.monkey1024.proxy 包下的  SomeServiceProxy.java

 1 package com.monkey1024.proxy;
 2 import com.monkey1024.service.ISomeService;
 3 import com.monkey1024.service.SomeServiceImpl;
 4 
 5 // 代理类     
 6 public class SomeServiceProxy implements ISomeService {
 7 
 8     private ISomeService target;
 9 
10     public SomeServiceProxy() {
11         // 放在无参构造器中: 一创建这个代理对象 ,就把目标对象创建了
12         // 创建 目标对象
13         target = new SomeServiceImpl();
14     }
15 
16     @Override
17     public String doFirst() {
18         
19         // 代理类 调用  目标方法
20         String result= target.doFirst();
21         
22         // 这里实现了增强
23         return result.toUpperCase();
24     }
25 
26     @Override
27     public void doSecond() {
28         // 代理类 调用  目标方法
29         target.doSecond();
30     }
31 }

 

执行结果:

执行doFirst()方法
result = ABCDE
执行doSecond()方法

 

 

画图分析:

技术图片

 

 


 

扩展:

   Javac 命令启动JVM时候 做了什么:

   jvm在 JDK的 jre 的 bin 目录下的 client 目录下  : jvm.dll      这就是JVM,它由C++编写而成。(所以说,Java的底层是由C++实现的)

   jvm在启动时,会加载一个BootstrapClassLoader类(引导策略类加载器)。目的是:加载Java里的核心类库。  jdk下的jre下的lib目录中的 rt.jar 。( java核心类库 )

   紧接着,还会加载2个类。一个是ExtClassLoader,另一个是AppClassLoader 。

            - 其中 AppClassLoader类加载器 在运行时 需要检查 路径,查找path路径。

    

 


 

动态代理的实现  (2种)

     不需要创建代理类,而是 通过 工具 或 工厂 来生成代理对象。

 

 

 


 

方式1.   jdk的Proxy动态代理

 

无需手动创建 代理类

1.4  com.monkey1024.test 包下 MyTest.java

 

 1 package com.monkey1024.test;
 2 import java.lang.reflect.InvocationHandler;
 3 import java.lang.reflect.Method;
 4 import java.lang.reflect.Proxy;
 5 
 6 import com.monkey1024.service.ISomeService;
 7 import com.monkey1024.service.SomeServiceImpl;
 8 public class MyTest {
 9 
10     public static void main(String[] args) {
11         
12         
13         // 创建目标对象
14         ISomeService target = new SomeServiceImpl();
15         
16         // 通过工具得到 代理对象
17         ISomeService service = (ISomeService) Proxy.newProxyInstance(
18                                 
19                                 target.getClass().getClassLoader(),  // 目标类的类加载器
20                                 target.getClass().getInterfaces(),   // 目标类所实现的所有接口
21                                 
22                                 new InvocationHandler() {       // 创建实现了InvocationHandler接口的匿名内部类
23                                     
24                                     // proxy: 代理对象 
25                                     // method:目标方法
26                                     // args:  目标方法的参数列表
27                                     
28                                     @Override
29                                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
30                                         
31                                         // 调用目标方法,获取到结果
32                                         // 表示:该方法的调用者是target
33                                         Object result = method.invoke(target, args); 
34                                         
35                                         // 再对获取到的结果,做增强操作
36                                          
37                                         if (result !=null ) {   // 做判断 避免 空指针异常
38                                             result = ((String) result).toUpperCase();
39                                         }
40                                         return result;
41                                     }
42                                 });
43         
44         // 使用代理对象 调用 目标方法1
45         String result = service.doFirst();
46         System.out.println("result ="+result);
47         
48         // 使用代理对象 调用 目标方法2
49         service.doSecond();
50         
51     }
52 }

 

 

结果:

执行doFirst()方法
result =ABCDE
执行doSecond()方法

 

 

总结:

 

    使用jdk的Proxy动态代理,要求 目标类 必须要实现接口

    因为其底层执行原理,与静态代理的相同。

 


 

方式2.   cglib动态代理

 

CGLIB(Code Generation Library):是一个开源项目,是一个强大的、高性能的、高质量的代码生成类库。

  它可以在运行期扩展和增强 Java 类。Hibernate 用它来实现持久对象的字节码的动态生成,Spring 用它来实现 AOP 编程。

 

 

CGLIB 代理的生成原理:

  是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象。

  所以,使用CGLIB 生成动态代理,要求目标类必须能够被继承,即不能是 final 的类

以上是关于静态代理的主要内容,如果未能解决你的问题,请参考以下文章

片段内部静态类和gradle问题

代理模式之静态代理实现代码

代理模式(静态代理)

Forge Viewer - 如何在场景中访问(或获取渲染/片段代理)克隆的网格?

静态代理模式代码演示

Spring Spring中的静态代理