【JAVA SE】 反射机制
2021/9/10 1:04:04
本文主要是介绍【JAVA SE】 反射机制,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
JDK的java.lang.reflect包提供了反射支持。
1.Class类
程序运行期间,Java会给每个对象都维护一个运行时类型标识。该对象保存着该类的信息。
三种获取Class类的方法:
- object.getClass()
- Class.forName(类的全路径名)
- Employee.class
2.反射
java.lang.reflect包下有三个类Field、Method、Constructor分别描述了域、方法、构造器。可以获取类的所有信息。
Class类的getFields、getMethods、getConstructors方法会返回响应的的信息。
两个简单例子
下面实现了两个相同的操作,不同的是在反射中我们可以事先没有得到该类,通过反射的方法去new 实例,并调用方法。
3.动态代理
代理类在程序运行时完成创建的代理方式被成为动态代理。
动态代理相对于静态代理来说,耦合性更低。像静态代理如果需要代理100个接口,就得写100个代理类,而动态代理只需要一个。
3.1 JDK动态代理
接口以及被代理对象
public interface House { void sell(); } public class Bieshu implements House{ @Override public void sell() { System.out.println("卖了大别墅~"); } }
InvocationHandler
public class HouseHandler implements InvocationHandler { private Object obj; public HouseHandler(Object obj){ super(); this.obj = obj; } @Override public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable { System.out.println("出售前~"); method.invoke(obj); System.out.println("出售后~"); return null; } }
main方法
public static void main(String[] args) { Bieshu bieshu = new Bieshu(); HouseHandler houseHandler = new HouseHandler(bieshu); Class<?> bieshuClass = bieshu.getClass(); House proxyInstance = (House) Proxy.newProxyInstance(bieshuClass.getClassLoader(), bieshuClass.getInterfaces(), houseHandler); proxyInstance.sell(); } -------------------------------- 出售前~ 卖了大别墅~ 出售后~
所以总的来说JDK代理就是两层代理,Proxy代理了InvocationHandler,而InvocationHandler代理了被代理类。
3.2 CGLib代理
代理的目的是构造一个和被代理对象有相同行为的对象,所以不一定需要通过持有的方式来实现,也可以通过继承,并重写父类方法来实现。CGLib就是如此。
被代理类
public class HelloService { public HelloService() { System.out.println("HelloService构造"); } /** * 该方法不能被子类覆盖,Cglib是无法代理final修饰的方法的 */ final public String sayOthers(String name) { System.out.println("HelloService:sayOthers>>" + name); return null; } public void sayHello() { System.out.println("HelloService:sayHello"); } }
MethodInterceptor
public class CglibProxy implements MethodInterceptor { @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { // 这里增强 System.out.println("收钱"); return arg3.invokeSuper(arg0, arg2); } }
main
public static void main(String[] args) { // 通过CGLIB动态代理获取代理对象的过程 Enhancer enhancer = new Enhancer(); // 设置enhancer对象的父类 enhancer.setSuperclass(HelloService.class); // 设置enhancer的回调对象 enhancer.setCallback(new MyMethodInterceptor()); // 创建代理对象 HelloService proxy= (HelloService)enhancer.create(); // 通过代理对象调用目标方法 proxy.sayHello(); }
3.3 两者的区别
-
JDK动态代理是面向接口的
-
CGLib动态代理是通过字节码底层继承来实现的。
-
spring中当被代理类是实现类就会使用JDK代理,否则则用CGLib
-
CGLib创建动态代理对象在运行中比JDK代理的快很多,所以使用单例时比较适合。
-
CGLib创建动态代理对象在创建中比JDK代理的慢很多
-
目前随着JDK的版本提高,JDK动态代理的效率已经比CGLib高了。
public class ReflectTest { public static class BasketBall{ private int price; public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } } public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { // 1.正常调用 BasketBall basketBall = new BasketBall(); basketBall.setPrice(10); // 2.反射调用 System.out.println(basketBall.getClass().getName()); String name = "reflect.ReflectTest$BasketBall"; Class classBasketBall = Class.forName(name); Method method = classBasketBall.getMethod("setPrice", int.class); Constructor constructor = classBasketBall.getConstructor(); Object instance = constructor.newInstance(); method.invoke(instance,10); } }
3.4 AOP
AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。在OOP中允许定义从上到下的关系,但是对横向关系就无能为力了,AOP就提供了横向的处理能力。比如说日志,权限校验等功能会横切在代码中,这会导致代码不能复用。
spring 通过动态代理实现了AOP。
这篇关于【JAVA SE】 反射机制的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-07-04TiDB 资源管控的对撞测试以及最佳实践架构
- 2024-07-03万字长文聊聊Web3的组成架构
- 2024-07-02springboot项目无法注册到nacos-icode9专业技术文章分享
- 2024-06-26结对编程到底难不难?答案在这里
- 2024-06-19《2023版Java工程师》课程升级公告
- 2024-06-15matplotlib作图不显示3D图,怎么办?
- 2024-06-1503-Loki 日志监控
- 2024-06-1504-让LLM理解知识 -Prompt
- 2024-06-05做软件测试需要懂代码吗?
- 2024-06-0514-ShardingSphere的分布式主键实现