Java-反射2
2022/4/16 1:12:32
本文主要是介绍Java-反射2,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1.反射
反射的练习:
- 用 public void setProperty(Object obj, String propertyName, Object value){} 方法将 反射获取值 封装成一个方法,然后再通过调用方法通过传参的方式调用方法;
注意事项:
- 因为方法中的参数,不知道是不是私有的,所以调用 getDeclaredField() 方法。并设置暴力访问;
public class Tool { public void setProperty(Object obj, String propertyName, Object value){ //通过反射实现 //通过反射获取对象的字节码文件对象 Class<?> c = obj.getClass(); //通过字节码文件对象,获取对应的成员变量形成一个对象 try { Field declaredField = c.getDeclaredField(propertyName); //暴力访问 declaredField.setAccessible(true); declaredField.set(obj,value); } catch (Exception e) { e.printStackTrace(); } } }
调用方法
public class ToolText { public static void main(String[] args) { Person p = new Person(); // p.name = "阿涛"; // 这里因为 name 是私有属性,不能直接获取 //可以通过自己写的工具来进行获取 Tool tool = new Tool(); tool.setProperty(p, "name", "阿涛"); tool.setProperty(p, "age", 18); tool.setProperty(p, "address", "安徽安庆"); tool.setProperty(p, "id", "1001"); System.out.println(p); } }
动态代理
- 动态代理就是,在程序运行期,创建目标对象的代理对象,并对目标对象中的方法进行功能性增强的一种技术。在生成代理对象的过程中,目标对象不变,代理对象中的方法是目标对象方法的增强方法。可以理解为运行期间,对象中方法的动态拦截,在拦截方法的前后执行功能操作。
代理类在程序运行期间,创建的代理对象称之为动态代理对象。这种情况下,创建的代理对象,并不是事先在Java代码中定义好的。而是在运行期间,根据我们在动态代理对象中的“指示”,动态生成的。也就是说,你想获取哪个对象的代理,动态代理就会为你动态的生成这个对象的代理对象。动态代理可以对被代理对象的方法进行功能增强。有了动态代理的技术,那么就可以在不修改方法源码的情况下,增强被代理对象的方法的功能,在方法执行前后做任何你想做的事情。
通俗而言:
代理就是被代理者没有能力或者不愿意去做某件事情,需要找个人代替自己完成这件事,动态代理业务功能(方法)进行代理的
关键步骤:
- 1.必须要有接口,实现类实现接口(代理通常是基于接口实现的)
- 2.创建一个实现类对象,该对象为业务对象,紧接着为业务对象做一个代理对象
代码来袭:
以前的方法:
业务代码(接口)
public interface UserDao { void add(); void delete(); void update(); void select(); }
实现类(实现接口)
public class UserDaoImpl implements UserDao{ @Override public void add() { // System.out.println("权限校验"); System.out.println("增加数据"); // System.out.println("日志记录"); } @Override public void delete() { // System.out.println("权限校验"); System.out.println("删除数据"); // System.out.println("日志记录"); } @Override public void update() { // System.out.println("权限校验"); System.out.println("更新数据"); // System.out.println("日志记录"); } @Override public void select() { // System.out.println("权限校验"); System.out.println("查询数据"); // System.out.println("日志记录"); } }
调用实现类方法
public class UserDemo { public static void main(String[] args) { UserDaoImpl userDao = new UserDaoImpl(); userDao.add(); userDao.delete(); userDao.update(); userDao.select(); System.out.println("================================="); //真实的开发环境不应该就输出一句话就完事了 //更多的是实际操作 //通常在操作数据库前后都有额外的步骤,在操作之前一般都会有一个权限校验 //不是任何人都可以操作的 //操作完成后也会留下日志记录 //通过我们简单地分析并改动后,显然实现的我们想要的功能,但是也仅限于这个案例 //如果我们在其他这样的案例中社交到的权限检验和日志记录 //还是以这样的方式进行修改,会显得非常麻烦 } }
出现问题
- 业务对象的每个方法在调用前后都需要进行权限校验和日志记录。存在大量重复代码.
改变:动态代理
动态代理代码
- 此代码必须实现
InvocationHandler 接口,然后重写其中的invoke 方法
代理者的代码为:
public class InvocationHandlerImpl implements InvocationHandler { private Object proxy1; //目标对象,将来要给谁做代理,就将谁传进来 //创建一个无参构造,将这个对象传进来 InvocationHandlerImpl(Object proxy1){ this.proxy1 = proxy1; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("权限校验"); Object o = method.invoke(proxy1, args); System.out.println("日志记录"); return o; } }
被代理者的代码:
package com.bigdat.java.day29; import java.lang.reflect.Proxy; /* 动态代理 */ public class Text { public static void main(String[] args) { UserDaoImpl userDao = new UserDaoImpl(); // 注意点:向下转型必须是转型为其接口 UserDao p = (UserDao)Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), new InvocationHandlerImpl(userDao)); p.add(); p.delete(); p.select(); p.update(); System.out.println("========================================================================="); TeacherDaoImpl teacherDao = new TeacherDaoImpl(); TeacherDao o = (TeacherDao) Proxy.newProxyInstance(teacherDao.getClass().getClassLoader(), teacherDao.getClass().getInterfaces(), new InvocationHandlerImpl(teacherDao)); o.login(); o.zhuce(); } }
一个代理可以不仅可以代理UserDao,
还可以代理老师
teacherDao 代码:
public interface TeacherDao { void login(); void zhuce(); }
老师的实现类 TeacherDaoInpl
public class TeacherDaoImpl implements TeacherDao{ @Override public void login() { System.out.println("用户登录"); } @Override public void zhuce() { System.out.println("用户注册"); } }
代理老师的方法和代理User的方法写在一起了
反射练习:通过配置文件,反射出其中的方法;
配置文件如下:
···
className=com.bigdat.java.day29.Person
methodName=fun2
···
反射代码如下:
package com.bigdat.java.day29; import java.io.FileReader; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Properties; /* 通过配置文件运行类中的方法 Properties 一般情况下,配置文件有以下几种格式:基本上都是以键值对的方式存在 格式1: username: xxx password: xxx xxx: xxx 格式2: <name>className</name> <value>com.xxx.xxx.xx</value> 格式3: name=xiaohu age=18 password=123456 */ public class ReflexTest1 { public static void main(String[] args) throws Exception{ //学习反射之前 // Person person = new Person(); // person.fun2(); Properties prop = new Properties(); FileReader fr = new FileReader("D:\\Softwore_java\\projects\\基础语法1\\src\\com\\" + "bigdat\\java\\day29\\configure.txt"); prop.load(fr); fr.close(); //获取数据 String className = prop.getProperty("className"); System.out.println(className); String methodName = prop.getProperty("methodName"); System.out.println(methodName); //通过反射实现 Class<?> c = Class.forName(className); Constructor<?> con1 = c.getConstructor(); Object o = con1.newInstance(); Method fun2 = c.getDeclaredMethod(methodName, String.class); fun2.setAccessible(true); fun2.invoke(o,"你好!"); } }
反射练习:我给你ArrayList的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢?
package com.bigdat.java.day29; import java.lang.reflect.Method; import java.util.ArrayList; /* 我给你ArrayList<Integer>的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢? */ public class ReflexText2 { public static void main(String[] args) throws Exception { ArrayList<Integer> list = new ArrayList<Integer>(); list.add(100); list.add(1023); //通过反射来实现 Class<? extends ArrayList> c = list.getClass(); Method add = c.getMethod("add", Object.class); // 使用 Object 类型,表示所有类型的数据都能加 add.invoke(list,"我擦"); add.invoke(list,"这都行?"); add.invoke(list,10.23); } }
这篇关于Java-反射2的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-26Mybatis官方生成器资料详解与应用教程
- 2024-11-26Mybatis一级缓存资料详解与实战教程
- 2024-11-26Mybatis一级缓存资料详解:新手快速入门
- 2024-11-26SpringBoot3+JDK17搭建后端资料详尽教程
- 2024-11-26Springboot单体架构搭建资料:新手入门教程
- 2024-11-26Springboot单体架构搭建资料详解与实战教程
- 2024-11-26Springboot框架资料:新手入门教程
- 2024-11-26Springboot企业级开发资料入门教程
- 2024-11-26SpringBoot企业级开发资料详解与实战教程
- 2024-11-26Springboot微服务资料:新手入门全攻略