静态代理
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 的类
以上是关于静态代理的主要内容,如果未能解决你的问题,请参考以下文章