首先来讲Java中的反射,在Java中,当我们在使用一个类时,该类的字节码就会加载进内存,所以当我们也可以通过调用这个类的字节码去调用对象的一些属性以及设置并且不受关键字的修饰, 注意:这里要啰嗦的一点是,无论这个类去new了多少此次,该类的字节码是不会变化的,它就像是一个文件的骨架一样,无论它以后披什么皮,骨架只有一个,(画皮的灵感) 下面介绍调用字节码的几种方式:
通过创建一个该类的子类对象去调用getclass方法从而得到该类的字节码文件
通过调用该类的静态属性class可以调出该类的额字节码文件对象。
同样是通过调用Class类中的静态方法来取该类的字节码文件对象。方法中的String类型是指的这个类的全路径。全路径:包名+类名。 通常第三种方法比较常用。 接下来,当我们拿到字节码文件对象后,就可以对这个类进行刨析了。
如果该构造方法私有,则需要在调newInstance方法前再加上一句: declaredConstructor.setAccessible(true);//取消语法检测
给私有字段设值时需要在调用set方法前需要取消语法检测
配置文件的作用是在以后程序运行中如果需要修改则只需通过配置文件修改而不必更改原码。 简单的例子如下:
Class aClass = list.getClass(); Method add = aClass.getDeclaredMethod("add", Object.class); add.setAccessible(true); add.invoke(list, "张三"); System.out.println(list);通过反射越过泛型检查,将任意类型添加到集合中。
先贴代码: 接口如下:
public interface UserDao { public abstract void add(); public abstract void delete(); public abstract void update(); public abstract void query(); } 实现类如下: 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 query() { //System.out.println("校验用户权限的代码"); System.out.println("查询一条数据"); // System.out.println("记录日志"); } } 测试类如下: public class MyTest { public static void main(String[] args) { UserDao userDao = new UserDaoImpl(); //userDao.add(); //userDao.delete(); //我们可以采用一种动态代理的模式,增强某个功能 //比如我们想在 add方法之前,增加校验功能,add 后面 增加记录日志功能 //这种动态代理的方式,不需要我们去改原有的代码,能实现对某个功能进行增强 //这种动态代理模式,也Spring框架采用一种对功能进行增强的模式 UserDao proxy = GetProxyUtils.getProxy(userDao); proxy.add(); System.out.println("----------------"); proxy.delete(); System.out.println("----------------"); proxy.query(); System.out.println("----------------"); proxy.update(); //代理模式:动态代理是Java给我们提供的,动态代理,要求必须要有接口 //如果一个类没有接口,那么动态代理用不了,但是第三方的框架,可以针对没有接口的类进行代理,这种方式叫做cglib代理 } } 代理类: public static UserDao getProxy(UserDao dao) { //java.lang.reflect 类 Proxy 代理公司,帮你在运行期间,生成一个代理人对象,帮你完成功能的增强 //我们要在运行期间,创建一个代理对象 //static Object newProxyInstance (ClassLoader loader, Class < ?>[]interfaces, InvocationHandler h) //返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。 //loader: //类加载器 //interfaces: //接口对应的一个Class数组 //InvocationHandler: //这个其实就是要代理对象所做的事情的一个类的封装 //InvocationHandler 是代理实例的调用处理程序 实现的接口。 UserDao obj = (UserDao) Proxy.newProxyInstance(dao.getClass().getClassLoader(), dao.getClass().getInterfaces(), new InvocationHandler() {0 /** * * @param proxy 代理对象 * @param method 被代理类中方法的对象 * @param args 方法中的参数 * @return * @throws Throwable */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //在被代理人,核心功能执行之前,可以让代理对象,帮你做你做准备工作, //权限校验 System.out.println("权限的校验"); Object invoke = method.invoke(dao); System.out.println("记录日志"); return invoke; } }); return obj;//返回代理对象 } }通俗一点的说就是当你去实现一个接口发现它功能不够时,你就可以创建一个代理类,让它可以跟实现类组合实现更多功能。