精华内容
下载资源
问答
  • Java笔试面试-反射和动态代理

    万次阅读 多人点赞 2019-09-19 09:28:41
    简单来说就是通过反射,可以在运行期间获取、检测调用对象的属性方法。 反射的使用场景 1.编程工具 IDEA 或 Eclipse 等,在写代码时会有代码(属性或方法名)提示,就是因为使用了反射; 2.很多知名的框架,为了...

    反射

      反射机制是 Java 语言提供的一种基础功能,赋予程序在运行时自省(introspect)的能力。简单来说就是通过反射,可以在运行期间获取、检测和调用对象的属性和方法。

    反射的使用场景

    1.编程工具 IDEA 或 Eclipse 等,在写代码时会有代码(属性或方法名)提示,就是因为使用了反射;
    2.很多知名的框架,为了让程序更优雅更简洁,也会使用到反射。

    例如,Spring 可以通过配置来加载不同的类,调用不同的方法,代码如下所示:

    <bean id="person" class="com.spring.beans.Person" init-method="initPerson">
    </bean>
    

    例如,MyBatis 在 Mapper 使用外部类的 Sql 构建查询时,代码如下所示:

    @SelectProvider(type = PersonSql.class, method = "getListSql")
    List<Person> getList();
    class PersonSql {
        public String getListSql() {
            String sql = new SQL() {{
                SELECT("*");
                FROM("person");
            }}.toString();
            return sql;
        }
    }
    

    3.数据库连接池,也会使用反射调用不同类型的数据库驱动,代码如下所示:

    String url = "jdbc:mysql://127.0.0.1:3306/mydb";
    String username = "root";
    String password = "root";
    Class.forName("com.mysql.jdbc.Driver");
    Connection connection = DriverManager.getConnection(url, username, password);
    

    反射的基本使用

    使用反射调用类中的方法,分为三种情况:

    • 调用静态方法
    • 调用公共方法
    • 调用私有方法

    假设有一个实体类 MyReflect 包含了以上三种方法,代码如下:

    package com.interview.chapter4;
    class MyReflect {
        // 静态方法
        public static void staticMd() {
            System.out.println("Static Method");
        }
        // 公共方法
        public void publicMd() {
            System.out.println("Public Method");
        }
        // 私有方法
        private void privateMd() {
            System.out.println("Private Method");
        }
    }
    

    ① 反射调用静态方法

    Class myClass = Class.forName("com.interview.chapter4.MyReflect");
    Method method = myClass.getMethod("staticMd");
    method.invoke(myClass);
    

    ② 反射调用公共方法

    Class myClass = Class.forName("com.interview.chapter4.MyReflect");
    // 创建实例对象(相当于 new )
    Object instance = myClass.newInstance();
    Method method2 = myClass.getMethod("publicMd");
    method2.invoke(instance);
    

    ③ 反射调用私有方法

    Class myClass = Class.forName("com.interview.chapter4.MyReflect");
    // 创建实例对象(相当于 new )
    Object object = myClass.newInstance();
    Method method3 = myClass.getDeclaredMethod("privateMd");
    method3.setAccessible(true);
    method3.invoke(object);
    

    反射总结
      反射获取调用类可以通过 Class.forName(),反射获取类实例要通过 newInstance(),相当于 new 一个新对象,反射获取方法要通过 getMethod(),获取到类方法之后使用 invoke() 对类方法进行调用。如果是类方法为私有方法的话,则需要通过 setAccessible(true) 来修改方法的访问限制。

    动态代理

      动态代理可以理解为,本来应该自己做的事情,却交给别人代为处理,这个过程就叫做动态代理。

    动态代理的使用场景

      动态代理被广为人知的使用场景是 Spring 中的面向切面编程(AOP)。例如,依赖注入 @Autowired 和事务注解 @Transactional 等,都是利用动态代理实现的。动态代理还可以封装一些 RPC 调用,也可以通过代理实现一个全局拦截器等。

    动态代理和反射的关系

      JDK 原生提供的动态代理就是通过反射实现的,但动态代理的实现方式还可以是 ASM(一个短小精悍的字节码操作框架)、cglib(基于 ASM)等,并不局限于反射。

    JDK 原生动态代理和 cglib 的实现

    1.JDK 原生动态代理

    interface Animal {
        void eat();
    }
    class Dog implements Animal {
        @Override
        public void eat() {
            System.out.println("The dog is eating");
        }
    }
    class Cat implements Animal {
        @Override
        public void eat() {
            System.out.println("The cat is eating");
        }
    }
    
    // JDK 代理类
    class AnimalProxy implements InvocationHandler {
        private Object target; // 代理对象
        public Object getInstance(Object target) {
            this.target = target;
            // 取得代理对象
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("调用前");
            Object result = method.invoke(target, args); // 方法调用
            System.out.println("调用后");
            return result;
        }
    }
    
    public static void main(String[] args) {
        // JDK 动态代理调用
        AnimalProxy proxy = new AnimalProxy();
        Animal dogProxy = (Animal) proxy.getInstance(new Dog());
        dogProxy.eat();
    }
    

    注意: JDK Proxy 只能代理实现接口的类(即使是 extends 继承类也是不可以代理的)

    2.cglib 动态代理

      要是用 cglib 实现要添加对 cglib 的引用,如果是 maven 项目的话,直接添加以下代码:

    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.2.12</version>
    </dependency>
    

    cglib 的具体实现,请参考以下代码:

    class Panda {
        public void eat() {
            System.out.println("The panda is eating");
        }
    }
    class CglibProxy implements MethodInterceptor {
        private Object target; // 代理对象
        public Object getInstance(Object target) {
            this.target = target;
            Enhancer enhancer = new Enhancer();
            // 设置父类为实例类
            enhancer.setSuperclass(this.target.getClass());
            // 回调方法
            enhancer.setCallback(this);
            // 创建代理对象
            return enhancer.create();
        }
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("调用前");
            Object result = methodProxy.invokeSuper(o, objects); // 执行方法调用
            System.out.println("调用后");
            return result;
        }
    }
    public static void main(String[] args) {
        // cglib 动态代理调用
        CglibProxy proxy = new CglibProxy();
        Panda panda = (Panda)proxy.getInstance(new Panda());
        panda.eat();
    }
    

    以上程序执行的结果:

    调用前
    
    The panda is eating
    
    调用后
    

      由以上代码可以知道,cglib 的调用通过实现 MethodInterceptor 接口的 intercept 方法,调用 invokeSuper 进行动态代理的。它可以直接对普通类进行动态代理,并不需要像 JDK 代理那样,需要通过接口来完成,值得一提的是 Spring 的动态代理也是通过 cglib 实现的。

    注意:cglib 底层是通过子类继承被代理对象的方式实现动态代理的,因此代理类不能是最终类(final),否则就会报错 java.lang.IllegalArgumentException: Cannot subclass final class xxx。

    面试笔试题

    1.动态代理解决了什么问题?

    答:首先它是一个代理机制,代理可以看作是对调用目标的一个包装,这样我们对目标代码的调用不是直接发生的,而是通过代理完成,通过代理可以让调用者与实现者之间解耦。比如进行 RPC 调用,通过代理,可以提供更加友善的界面;还可以通过代理,做一个全局的拦截器。

    2.动态代理和反射的关系是什么?

    答:反射可以用来实现动态代理,但动态代理还有其他的实现方式,比如 ASM(一个短小精悍的字节码操作框架)、cglib 等。

    3.以下描述错误的是?

    A:cglib 的性能更高
    B:Spring 中有使用 cglib 来实现动态代理
    C:Spring 中有使用 JDK 原生的动态代理
    D:JDK 原生动态代理性能更高

    答:D

    题目解析:Spring 动态代理的实现方式有两种:cglib 和 JDK 原生动态代理。

    4.请补全以下代码?

    class MyReflect {
        // 私有方法
        private void privateMd() {
            System.out.println("Private Method");
        }
    }
    class ReflectTest {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
            Class myClass = Class.forName("MyReflect");
            Object object = myClass.newInstance();
            // 补充此行代码
            method.setAccessible(true);
            method.invoke(object);
        }
    }
    

    答:Method method = myClass.getDeclaredMethod("privateMd");

    题目解析:此题主要考的是私有方法的获取,私有方法的获取并不是通过 getMethod() 方式,而是通过 getDeclaredMethod() 获取的。

    5.cglib 可以代理任何类这句话对吗?为什么?

    答:不完全对,因为 cglib 只能代理可以有子类的普通类,对于像最终类(final),cglib 是不能实现动态代理的,因为 cglib 的底层是通过继承代理类的子类来实现动态代理的,所以不能被继承类无法使用 cglib。

    6.JDK 原生动态代理和 cglib 有什么区别?

    答:JDK 原生动态代理和 cglib 区别如下:

    • JDK 原生动态代理是基于接口实现的,不需要添加任何依赖,可以平滑的支持 JDK 版本的升级;
    • cglib 不需要实现接口,可以直接代理普通类,需要添加依赖包,性能更高。

    7.为什么 JDK 原生的动态代理必须要通过接口来完成?

    答:这是由于 JDK 原生设计的原因,动态代理的实现方法 newProxyInstance() 的源码如下:

    /**
     * ......
     * @param   loader the class loader to define the proxy class
     * @param   interfaces the list of interfaces for the proxy class to implement
     * ......
     */ 
    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
    // 省略其他代码
    

    可以看到,前两个参数的声明:

    • loader:为类加载器,也就是 target.getClass().getClassLoader()
    • interfaces:接口代理类的接口实现列表

    因此,要使用 JDK 原生的动态只能通过实现接口来完成。

    展开全文
  • 反射动态代理关系

    千次阅读 2020-03-11 20:50:48
    先展示下mybatis的动态代理是怎样的 结合上一篇文章实践的 String resource = "mybatis.xml"; InputStream resourceAsStream = Resources.getResourceAsStream(resource); SqlSessionFactory factory = new ...

    先展示下mybatis的动态代理是怎样的

    结合上一篇文章实践的

    String resource = "mybatis.xml";
            InputStream resourceAsStream = Resources.getResourceAsStream(resource);
    
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    SqlSession sqlSession = factory.openSession();
    // 不使用动态代理的情况下
    try{
        List<User> userList = sqlSession.selectList("com.wyl.mybatis.dao.UserDao.getUserList");
                System.out.println("**********"+JSON.toJSON(userList));
            }finally {
                sqlSession.close();
            }
            
    // 使用动态代理的情况下
     try{
                UserDao userDao = sqlSession.getMapper(UserDao.class);
                List<User> userList = userDao.getUserList();
                System.out.println("**********"+JSON.toJSON(userList));
            }finally {
                sqlSession.close();
            }
    

    这里就是mybatis最原始的代理实现方式,也是用反射机制完成的,

    反射

    // Test.java
    public class Test {
    
        public void sayHello(String name) {
            System.out.println("*******"+name);
        }
    }
    
    //MybatisApplication.java
    public class MybatisApplication {
        public static void main(String[] args) throws  Exception{
            Object instance = Class.forName(Test.class.getName()).newInstance();
            Method sayHell = instance.getClass().getMethod("sayHello", String.class);
            sayHell.invoke(instance,"hello");
    }
    
    // 再举一个例子
    // class.txt
    class=com.wyl.mybatis.controller.Test
    method=printLog
    
    // Texst.java
    public class Test {
        public void printLog(){
            System.out.println("****打印日志***8");
        }
    }
    
    //MybatisApplication.java
    public class MybatisApplication {
    
        public static void main(String[] args) throws  Exception{
            Properties properties = new Properties();
            properties.load(new FileReader("src/main/resources/class.txt"));
            String className = properties.getProperty("class");
            String methodName = properties.getProperty("method");
            Class<?> forName = Class.forName(className);
            Method method = forName.getMethod(methodName);
            method.invoke(forName.newInstance());
    }
    

    从上面可以知道,反射就是在程序执行之前根本就不知道要加载什么类和什么方法,只有通过程序运行中,动态的调用。

    JDK动态代理

    // UserDao.java
    public interface UserDao {
        void getMoney();
    }
    
    // UserDaoImpl.java
    @Slf4j
    public class UserDaoImpl implements UserDao {
    
        @Override
        public void getMoney() {
            log.info("******获得大量的美元****");
        }
    }
    
    > 需求需要记录人在什么时候获得金钱
    
    // JDKProxy.java
    @Slf4j
    public class JDKProxy implements InvocationHandler {
    
        private Object object;
        public JDKProxy(Object object) {
            this.object = object;
        }
        // 创建代理对象
        public  Object createProxy() {
            Object o = Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
            return o;
        }
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            log.info("*********当前时间->{}", DateUtil.format(LocalDateTime.now(),"YYYY-MM-dd:HH:mm:ss") );
            method.invoke(object, args);
            return null;
        }
    }
    
    // MybatisApplication.java
    public class MybatisApplication {
    
        public static void main(String[] args) throws  Exception{
            UserDaoImpl userDao = new UserDaoImpl();
            UserDao proxy= (UserDao) new JDKProxy(userDao).createProxy();
            proxy.getMoney();
    
    
    运行结果:
    11:45:44.330 [main] INFO com.wyl.mybatis.proxy.JDKProxy - *********当前时间->2020-03-10:11:45:44
    11:45:44.363 [main] INFO com.wyl.mybatis.dao.impl.UserDaoImpl - ******获得大量的美元****
    

    CGLIB动态代理

    // CGLIBProxy.java
    @Slf4j
    public class CGLIBProxy implements MethodInterceptor {
    
        private Object object;
    
        public CGLIBProxy(Object object) {
            this.object = object;
        }
    
        // 创建代理对象
        public Object createProxy() {
            Object o = Enhancer.create(object.getClass(), this);
            return o;
    
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    
            log.info("*********当前时间->{}", DateUtil.format(LocalDateTime.now(),"YYYY-MM-dd:HH:mm:ss") );
            methodProxy.invoke(object,objects);
            return null;
        }
    }
    
    
    // 先使用上面有接口的测试用例
    public class MybatisApplication {
        public static void main(String[] args) throws  Exception{
            UserDaoImpl userDao = new UserDaoImpl();
            UserDao proxy = (UserDao) new CGLIBProxy(userDao).createProxy();
            proxy.getMoney();
        }
        
    运行结果:
    14:49:32.938 [main] INFO com.wyl.mybatis.proxy.CGLIBProxy - *********当前时间->2020-03-10:14:49:32
    14:49:32.973 [main] INFO com.wyl.mybatis.dao.impl.UserDaoImpl - ******获得大量的美元****
    
    // 新建UserController.class
    @Slf4j
    public class UserController {
    
        public void getMoney() {
            log.info("**********获得大量的金钱*********");
        }
    }
    
    // MybatisApplication.java
    public class MybatisApplication {
    
        public static void main(String[] args) throws  Exception{
            UserController userController = new UserController();
            UserController proxy = (UserController) new CGLIBProxy(userController).createProxy();
            proxy.getMoney();
    }
    
    运行结果:
    14:53:04.621 [main] INFO com.wyl.mybatis.proxy.CGLIBProxy - *********当前时间->2020-03-10:14:53:04
    14:53:04.659 [main] INFO com.wyl.mybatis.controller.UserController - **********获得大量的金钱*********
    
    从这里可以看出无论是否有接口CGLIB代理都可以,那么JDK代理呢?接着测试
    
    public class MybatisApplication {
    
        public static void main(String[] args) throws  Exception{
            UserController userController = new UserController();
            UserController proxy= (UserController) new JDKProxy(userController).createProxy();
            proxy.getMoney();
    }
    运行结果:
    Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to com.wyl.mybatis.controller.UserController
    	at com.wyl.mybatis.MybatisApplication.main(MybatisApplication.java:29)
    
    可以看到,出现了类转换时,发生了不兼容的异常,所以说对于JDK动态代理来说,实现类一定要有接口。
    

    总结

    JDK动态代理其实是反射机制实现的aop动态代理,实现类一定要有接口;CGLIB动态代理是JDK动态代理的补充。在不用接口的情况下,也可以使用动态代理。

    展开全文
  • 反射和动态代理的区别

    千次阅读 2019-05-12 20:07:25
    步入正文:反射和动态代理的区别。 动态代理代理,前面已经有一篇文章说了他们的用法,http://blog.csdn.net/wltsysterm/article/details/64437634。 我们也都知道,动态代理其实用到了反射。那么笔者还是想论述下...

    步入正文:反射和动态代理的区别。

    动态代理,代理,前面已经有一篇文章说了他们的用法,http://blog.csdn.net/wltsysterm/article/details/64437634。

    我们也都知道,动态代理其实用到了反射。那么笔者还是想论述下初学者可能会进入的一个理解误区,因为我进入了,所以我就拿出来跟大家共享下。

    误区:为啥用动态代理不用反射

    1、网上其他论坛或者是博友已经有好多文章论述为啥使用动态代理,动态代理有什么作用。

    笔者这边也简单的帮忙概括下:

    1)动态代理,struts的拦截器用到,spring的aop用到,用动态代理可以增强委托类的方法,增强体现在:事物的统一控制,统一日志控制等

    2)解耦:实际调用的是代理类,实现调用处和委托类解耦(我的理解是:实现同一日志调用和委托类解耦)

    3)隐藏底层代码:只暴露出代理类给我们,委托类可以隐藏起来(这块内容有点牵强)

      比如有一些底层的代码,我们不想显示出源码,这个时候可以生成一个代理类,把这个代理类和要被调用的方法暴露出来,就可以实现调用委托类某个方法。
    

    上面这些作用直接通过反射可以做到吗

    好吧,答案是既可以又不可以。

    下面附上笔者理解过程写的代码

    String classfullpath = propertiesUtil.readValue(urlarr[0]);
    Class c = Class.forName(classfullpath);//获取到委托类的类

            //实例化对象
            Object target = c.newInstance();                     
            //反射调用方法,并返回值
                     Systerm.out.println("before say hello");
            //这边要求调用的方法的参数类型,参数个数都要知道
            Method action = c.getMethod(urlarr[1], new Class[]{String.class});
            obj = action.invoke(target , new Object[]{param});
    

    Systerm.out.println(“after sya hello”);

    看到这边大家觉得,好像可以产生统一日志的功能,但是其实不然,上面如果只是告诉我们委托类对象和要调用的方法,是不足以完成方法的调用,还需要参数类型和参数个数
    ,但是每个方法的参数类型和参数个数其实都是不一样的,所以这个实现是有点难处的。
    总结,反射是不能直接坐到动态代理的功能的。

    再说下动态代理,以cglib动态代理为例子,人家是通过子类调用父类实现方法调用。而且方法的调用是显示调用的,即调用哪个方法,这个方法的参数有哪些都是清楚的,所以人家重心其实还是放在方法增强功能上,通过写一个动态代理中介类,实现所有想要增强的委托类的方法增强,这点,单纯的反射是做不到的。


    作者:独行侠_阿涛
    来源:CSDN
    原文:https://blog.csdn.net/wltsysterm/article/details/68921463
    版权声明:本文为博主原创文章,转载请附上博文链接!

    展开全文
  • java反射和动态代理详解

    千次阅读 2017-09-29 09:50:05
    动态代理 反射

    前言:spring中AOP的原理就是java的动态代理机制,动态代理又与反射相关,所以回顾一下反射与动态代理的知识。

    反射

     Jvm利用类加载器将.class文件加载到jvm内存中,.class文件的二进制字节流转换为方法区的运行时数据结构,保存着类object的版本,字段,方法,接口等信息,同时在堆中生成每个类唯一的类型对象class对象,作为方法区类信息的访问入口。

    Java反射机制让我们在编译期之外的运行期获得任何一个类的class对象,得到方法区中的类的接口,方法,字段等信息,也可以在运行期实例化对象。

    • 实例化Class对象:
    Class<?> demo1 = Class.forname(“Reflect.name”);//通过全限定名实例化Class对象
    Class<?> demo2 = new Demo().getInstance();
    Class<?> demo3 = Demo.class;
    • 通过一个实例对象获取完整包名和类名:

    demo1.getClass().getName();

    • 通过Class对象实例化类的实例
    a)无参构造器实例化:
     Person p = (Person) demo1.newInstance();
    b)有参构造器实例化,先获取构造器:
    Constructor<?> cons[] = demo.getConstructors();
    Person p1 = (Person)cons[1].newInstance(“Rollen”);返回一个类的接口:
    Class<?> demo = Class.forname(“Reflect.person”);
    //保存所有的接口
    Class<?> intes[] = demo.getInterfaces();
    intes[i].getName();
    • 取得其他类的父类:
    Class<?> temp = demo.getSuperclass();
    temp.getName();
    • 获取其他类的构造函数:
    Constructor<?> cons[] = demo.getConstructors();
    • 获取其他类的属性(字段):

    //本类属性 (比如: public string name)
    Field[] field = demo.getDeclaredFields();
    //权限修饰符
    int mo = field[i].getModifiers();
    String priv = Modifier.toString(mo);
    //属性类型
    Class

    //调用Person类中的sayChina方法
    Method method = demo.getMethod(“sayChina”);
    method.invoke(demo.newInstance());
    
    //调用Person类中的sayHello方法
    Method method = demo.getMethod(“sayHello”,String.class,int.class);
    method.invoke(demo.newInstance(),”Rollen”,20);
    • 通过反射操作属性:
    Class<?> demo = Class.forname(“Reflect.Person”);
    Object obj = demo.newInstance();
    Field field = demo.getDeclaredField(“sex”);
    field.setAccessible(true);
    field.set(obj,”男”);//设置sex属性为“男”

    动态代理机制

     动态代理机制中有一个重要的类Proxy和一个重要接口InvocationHandler。先牢记三个概念:1.动态代理类,每一个动态代理类都是InvocationHandler的子类。2.代理对象,由Proxy.newProxyInstance(…)创建的代理对象,每一个代理对象都会关联一个动态代理类实例,当代理对象调用真实对象方法时会转换为对handler动态代理类的invoke方法的调用。 3.真实对象,我们想要代理的对象。

    介绍完动态代理类,代理对象和真实对象的概念,我们通过一个实例来真正地了解动态代理模式是如何实现的:

    首先定义一个Subject接口,定义rent()方法和hello()方法:

    package Invocation;
    
    /**
     * Created by kang on 17/9/28.
     */
    public interface Subject {
    
        public void rent();
    
        public void hello(String hello);
    }
    

    定义一个realSubject接口,这个类是真实对象,也就是被代理对象:

    package Invocation;
    
    /**
     * Created by kang on 17/9/28.
     */
    //真实对象
    public class realSubject implements Subject {
    
        @Override
        public void rent() {
            System.out.println("I want to rent my house!");
        }
    
        @Override
        public void hello(String hello) {
            System.out.println("hello  " +hello);
        }
    }
    

    定义一个动态代理类,每一个动态代理类都需要实现InvocationHandler接口,在动态代理类中传入真实对象,然后每个代理对象绑定一个动态代理类实例,且每个动态代理类均有一个invoke方法。

    package Invocation;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    /**
     * Created by kang on 17/9/28.
     */
    
    
    //动态代理类MyInvocationHandler是InvocationHandler的子类,必须实现invoke方法
    public class DynamicProxy implements InvocationHandler {
    
        //要代理的真实对象
        private Object object;
    
        //给要代理的真实对象赋值
        public DynamicProxy(Object object){
            this.object = object;
        }
    
        /**
         *
         * @param proxy  指创造的代理对象
         * @param method  指我们要代理的真实对象的某个方法的Method对象
         * @param args    指真实对象的某个方法的参数
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            //在代理真实对象前添加我们添加一些自己的操作
            System.out.println("before rent house");
    
            System.out.println("Method:" + method);
    
            //当代理对象调用真实对象的方法时,会自动跳转到动态代理类即InvocationHandler的子类的invoke方法来调用
            method.invoke(object,args);
    
            //代理真实对象后添加一些操作
            System.out.println("after rent house");
    
            return null;
        }
    }
    

    查看Client类:

    package Invocation;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    
    /**
     * Created by kang on 17/9/28.
     */
    public class Client {
    
        public static void main(String[] args) {
    
            //subject是真实对象,handler是动态代理类,往动态代理类传入真实对象
            Subject realsubject = new realSubject();
            InvocationHandler handler = new DynamicProxy(realsubject);
    
    
            /**
             * 通过Proxy的newProxyInstance方法创建代理对象
             * 1.第一个参数handler.getClass().getClassLoader()表示用动态代理类的类加载器加载代理对象
             * 2.第二个参数realSubject.getClass().getInterfaces()传入真实对象的接口,所以代理对象也可以调用接口,使用真实对象的方法。
             *
             * 3.第三个对对象handler让代理对象与动态代理类联系起来,当代理对象调用真实对象的方法时可以自动跳转到执行handler的invoke方法。
             *
             */
            Subject subject = (Subject) Proxy.newProxyInstance(
                    handler.getClass().getClassLoader(),realsubject.getClass().getInterfaces(),handler);
    
            System.out.println(subject.getClass().getName());
            subject.rent();
            subject.hello("nihao");
    
        }
    
    }
    

    我们先来看看控制台的输出:

    com.sun.proxy.$Proxy0
    before rent house
    Method:public abstract void Invocation.Subject.rent()
    I want to rent my house!
    after rent house
    before rent house
    Method:public abstract void Invocation.Subject.hello(java.lang.String)
    hello  nihao
    after rent house
    
    
    
    展开全文
  • Java反射机制允许程序在运行时判断分析任意一个类...java动态代理可以在不改变被调用对象源码的前提下,在被调用方法前后增加自己的操作,极大地降低了模块之间的耦合性,Java的动态代理就是利用了反射的特性来实现的。
  • Java反射和动态代理详解实例

    千次阅读 2014-09-09 14:26:14
    这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。  反射就是把Java类中的各种成分映射成相应的Java类。 Java反射机制主要提供了以下功能:  1、在运行时判断任意一个对
  • 在上篇博客中,我们说了反射的原理简单应用,这次我们说说反射更深一层的应用,即动态代理代理模式 定义 代理模式是为其他对象提供一种代理以控制对这个对象的访问。代理模式分为静态代理和动态代理。 原理 ...
  • AOP的实现原理—反射动态代理

    万次阅读 2017-03-12 11:01:39
    他(DynaPoxyHello)自动去代理执行被代理对象(Hello)中的每一个方法,一个java.lang.reflect.InvocationHandler接口就把我们的代理对象代理对象解藕了。但是,我们又发现还有一个问题,这个DynaPoxyHello对象只能...
  • 反射就是在程序运行的过程中,我们能知道任何一个类有哪些方法属性,并且能对它的方法属性进行调用,我们就把这种能动态获取对象信息调用对象方法的功能称之为反射反射都用于哪些场景 有些朋友在平时...
  • spring aop原理(动态代理反射

    千次阅读 2019-09-14 14:46:25
    spring aop面向切面编程,底层原理主要是动态代理代理目标方法,但是另外还有一个是反射,通过注解反射得到相应的方法,再进行相应的操作。 参考链接:https://www.zhihu.com/question/23641679 ...
  • 对于最近博主最近写博客的兴致大发,我也在思考:为什么而写博客?在互联网时代,无论你是牛人大咖,还是小白菜鸟,都有发表自己看法的权利。无论你是对的还是错的,都会在这个平台...同样,了解技术是一个深入拓展的
  • Java动态代理的底层是通过反射机制来实现的,反射是基础,动态代理Proxy类中有有相关反射代码。
  • 典型回答 反射机制是Java语言提供的一种基础功能,赋予...动态代理是一种方便运行时动态构建代理动态处理代理方法调用的机制,很多场景都是利用类似机制做到的。比如用来包装RPC调用、面向切面的编程(AOP)。...
  • 所以就模仿java中的spring的动态注入功能, 写了这么一段代码。这段代码我测试过还比较好用吧。 不过我认为还是用很多不合理的地方,一些bug存在。 这个我会在以后慢慢修改。也请大家给与指点。 笔者:咋个...
  • 谈谈 Java 反射机制,动态代理是基于什么原理?典型回答反射机制是 Java 语言提供的一种基础功能,赋予程序在运行时自省(introspect,官方用语)的能力。通过反射我们可以直接操作类或者对象,比如获取某个对象的类...
  • java(反射动态代理,==instanceof)

    千次阅读 2019-12-06 14:13:05
    什么是反射反射就是Reflection,Java的反射是指程序在运行期可以拿到一个对象的所有信息。 详解 除了int等基本类型外,Java的其他类型全部都是class(包括interface)。...无继承关系的数据类型无法赋值:...
  • 1、java的类加载机制,参考文档 ...JVM的类加载是通过ClassLoader及其子类来完成的,类的层次关系和加载顺序可以由下图来描述: 1)Bootstrap ClassLoader 负责加载$JAVA_HOME中jre/lib/rt.jar里所
  • Java两种动态代理JDK动态代理和CGLIB动态代理

    万次阅读 多人点赞 2018-08-07 15:33:35
    JDK动态代理 cglib动态代理 测试 代理模式 代理模式是23种设计模式的一种,他是指一个对象A通过持有另一个对象B,可以具有B同样的行为的模式。为了对外开放协议,B往往实现了一个接口,A也会去实现接口。但是B是...
  • java反射动态代理

    千次阅读 2014-09-27 23:24:11
    一直分不清的两个东西,今天记录一下,java反射动态代理 java反射:1、在运行时分析类的能力  2、在运行是查看对象  3、实现数组的操作代码  4、利用Method对象  在java.lang.reflect包中有三个类Field、...
  • RPC java实例 文章包括以下两个部分: RPC基本原理 RPC Java实例讲解 废话不多说,现在讲讲RPC到底是...看到这可能比较晕,没关系,我的理解是这样的,就是服务器上正在运行一个服务app,app有一个函数或接口plus(int
  • 一文弄懂:反射动态代理

    千次阅读 2020-01-08 10:36:51
    反射动态代理、Spring AOP 反射 反射是什么? 反射是程序在运行时可以动态的获取类的信息。包括: 类的属性 类的构造器 类的方法 反射可以在获取类的信息后调用其方法。 反射的应用场景 IDEA 可以知道类的方法...
  • JAVA反射代理

    2014-03-06 01:00:07
    使用反射技术获取类的结构信息 使用反射技术 动态创建对象 动态修改查询属性值 动态执行方法 动态创建数组并存取元素 使用静态代理实现添加日志功能 使用动态代理实现添加日志功能
  • JDKCGLib动态代理实现区别

    千次阅读 2019-12-02 16:38:25
    前言 上周五在电面试阿里时,被问到Spring AOP中JDKCGLib动态代理的区别?于是搜集网上相关知识点,在此整理一下,供大家参考...动态代理的代理关系是在运行时期确定的。在讲解两种动态代理区别之前,首先通过实...
  • 静态代理,JDK动态代理,Cglib动态代理详解

    千次阅读 热门讨论 2021-02-12 13:21:39
    文章目录一、代理模式二、静态代理三、动态代理 一、代理模式 代理模式(Proxy Pattern)是程序设计中的一种设计模式,他的特征是代理委托类实现有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、...
  • 1.总结并归纳反射中四大核心类(Class、Constructor、Method、Field)的常用操作...4.要求掌握静态代理模式原理(包括反射工厂创建)、会写出JDK提供的动态代理,知道cglib与JDK提供的动态代理之间的区别。 5.编程题: ...
  • 1)让代理对象真实对象建立联系(建立关系的过程会生成代理对象,基于java反射) 2)实现代理对象的代理逻辑方法 3.代理的作用(好处) 4.常用的代理技术有哪些 1)JDK动态代理 2)CGLIB动态代理 5.JDK动态...
  • JDKcglib动态代理原理详解

    千次阅读 2019-01-07 18:45:57
    AOP的基础是Java动态代理,了解使用两种动态代理能让我们更好地理解&nbsp;AOP,在讲解AOP之前,让我们先来看看Java动态代理的使用方式以及底层实现原理。转自https://www.jianshu.com/u/668d0795a95b本文是...
  • Java JDK 动态代理(AOP)使用及实现原理分析

    万次阅读 多人点赞 2019-05-08 21:28:06
    二、Java 动态代理类 三、JDK的动态代理怎么使用? 四、动态代理怎么实现的? 五、结论 一、什么是代理代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为...
  • 对于最近博主最近写博客的兴致大发,我也在思考:为什么而写博客?在互联网时代,无论你是牛人大咖,还是小白菜鸟,都有发表自己看法的权利。无论你是对的还是错的,都会在这个...同样,了解技术是一个深入拓展的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 55,157
精华内容 22,062
关键字:

反射和动态代理的关系