美文网首页SpringJAVA特性
Java基础:动态代理

Java基础:动态代理

作者: JackChen1024 | 来源:发表于2017-03-14 23:05 被阅读42次

    系列阅读

    概述

    在运行时,动态创建一组指定的接口的实现类对象(代理对象)!

    代理是实现AOP(面向切面编程)的核心和关键技术,动态代理的用途与装饰模式很相似,就是为了对某个对象进行增强。所有使用装饰者模式的案例都可以使用动态代理来替换。

    代理:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象。

    举例:春季回家买票让人代买

    动态代理:在程序运行过程中产生的这个对象

    而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理

    工作原理

    • client调用代理
    • 代理的构造方法接收一个invocationhandler参数
    • client调用代理的各个方法,代理的各个方法会把调用请求转发给invocationhandler
    • invocationhandler通过invoke()方法把调用请求分发给目标对象的各个方法
    动态代理

    1、在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib。

    2、Proxy类中的方法创建动态代理类对象

    public static Object newProxyInstance(
        ClassLoader loader,
        Class<?>[]interfaces,
        InvocationHandler h)
    

    返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。最终会调用InvocationHandler的方法

    3、InvocationHandler

    Object invoke(Object proxy,Method method,Object[] args)
    

    在代理实例上处理方法调用并返回结果。

    4、Proxy类中创建动态代理对象的方法的三个参数

    • ClassLoader对象
      定义了由哪个ClassLoader对象来对生成的代理对象进行加载

    • Interface对象的数组
      表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了

    • InvocationHandler对象
      表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

    每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke 方法来进行调用。

    5、InvocationHandler接口中invoke()方法的三个参数:

    • Object proxy:代表动态代理对象
    • Method method:代表正在执行的方法
    • Object[] args:代表调用目标方法时传入的实参
    动态代理

    6、Proxy.newProxyInstance()

    创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号

    动态代理的实现

    package cn.itcast_06;
    
    /*
     * 用户操作接口
     */
    public interface UserDao {
        public abstract void add();
        public abstract void delete();
        public abstract void update();
        public abstract void find();
    }
    
    package cn.itcast_06;
    
    public interface StudentDao {
        public abstract void login();
    
        public abstract void regist();
    }
    
    package cn.itcast_06;
    public class UserDaoImpl implements UserDao {
        @Override
        public void add() {
            System.out.println("添加功能");
        }
    
        @Override
        public void delete() {
            System.out.println("删除功能");
        }
    
        @Override
        public void update() {
            System.out.println("修改功能");
        }
        
        @Override
        public void find() {
            System.out.println("查找功能");
        }
    }
    
    package cn.itcast_06;
    
    public class StudentDaoImpl implements StudentDao {
    
        @Override
        public void login() {
            System.out.println("登录功能");
        }
    
        @Override
        public void regist() {
            System.out.println("注册功能");
        }
    }
    
    package cn.itcast_06;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class MyInvocationHandler implements InvocationHandler {
        private Object target; // 目标对象
    
        public MyInvocationHandler(Object target) {
            this.target = target;
        }
    
        @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; // 返回的是代理对象
        }
    }
    
    package cn.itcast_06;
    
    import java.lang.reflect.Proxy;
    
    public class Test {
        public static void main(String[] args) {
            UserDao ud = new UserDaoImpl();
            ud.add();
            ud.delete();
            ud.update();
            ud.find();
            System.out.println("-----------");
            // 我们要创建一个动态代理对象
            // Proxy类中有一个方法可以创建动态代理对象
            // public static Object newProxyInstance(ClassLoader loader,Class<?>[]
            // interfaces,InvocationHandler h)
            // 我准备对ud对象做一个代理对象
            MyInvocationHandler handler = new MyInvocationHandler(ud);
            UserDao proxy = (UserDao) Proxy.newProxyInstance(ud.getClass()
                    .getClassLoader(), ud.getClass().getInterfaces(), handler);
            proxy.add();
            proxy.delete();
            proxy.update();
            proxy.find();
            System.out.println("-----------");
    
            StudentDao sd = new StudentDaoImpl();
            MyInvocationHandler handler2 = new MyInvocationHandler(sd);
            StudentDao proxy2 = (StudentDao) Proxy.newProxyInstance(sd.getClass()
                    .getClassLoader(), sd.getClass().getInterfaces(), handler2);
            proxy2.login();
            proxy2.regist();
        }
    }
    

    Spring原理

    public class ProxyFactoryBean {
        private Object mTarget;
        private Advice mAdvice;
        
        public Object getProxy(){
            Object proxy = Proxy.newProxyInstance(
                    mTarget.getClass().getClassLoader(),
                    mTarget.getClass().getInterfaces(),
                    mHandler
            );
            return proxy;
        }
        
        private InvocationHandler mHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                mAdvice.beforeMethod(method);
                Object result = method.invoke(mTarget, args);
                mAdvice.afterMethod(method);
                return result;
            }
        };
        
        public void setTarget(Object target) {
            mTarget = target;
        }
    
        public void setAdvice(Advice advice) {
            mAdvice = advice;
        }
    
        public Object getTarget() {
            return mTarget;
        }
    
        public Advice getAdvice() {
            return mAdvice;
        }
    }
    
    public class BeanFactory {
        Properties mProperties = new Properties();
        public BeanFactory(InputStream in){
            try {
                mProperties.load(in);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        public Object getBean(String name){
            String classname = mProperties.getProperty(name);
            Object bean = null;
            try {
                Class clazz = Class.forName(classname);
                bean = clazz.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            if (bean instanceof ProxyFactoryBean){
                Object proxy = null;
                ProxyFactoryBean factoryBean = (ProxyFactoryBean) bean;
                Advice advice = null;
                try {
                    advice = (Advice) Class.forName(mProperties.getProperty(name+".advice")).newInstance();
                    Object target = Class.forName(mProperties.getProperty(name+".target")).newInstance();
                    factoryBean.setAdvice(advice);
                    factoryBean.setTarget(target);
                    proxy = factoryBean.getProxy();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return proxy;
            }
            return bean;
        }
    }
    
    public interface Advice {
        void beforeMethod(Method method);
        void afterMethod(Method method);
    }
    
    public class AopFrameworkTest {
        
        public static void main(String[] args) throws Exception {
            InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties");
            Object bean = new BeanFactory(ips).getBean("xxx");
            System.out.println(bean.getClass().getName());
            ((Collection)bean).clear();
        }
    }
    

    相关文章

      网友评论

        本文标题: Java基础:动态代理

        本文链接:https://www.haomeiwen.com/subject/rdyknttx.html