码迷,mamicode.com
首页 > 编程语言 > 详细

java-动态代理

时间:2019-11-07 19:37:09      阅读:112      评论:0      收藏:0      [点我收藏+]

标签:限制   actor   入参   code   增强   过程   tac   get   实例化   

一、Java自带的动态代理

1、概述: 

JDK动态代理主要涉及java.lang.reflect包下的Proxy类和InvocationHandler接口。 JDK代理实现的三个要点:

  通过java.lang.reflect.Proxy类来动态生成代理类
  代理类要实现InvocationHandler接口
  JDK代理只能基于接口进行动态代理

2、代码结构

                            技术图片

 

 

3、Jdk_ProxyService

package com.turtle.jdk;

public interface Jdk_ProxyService {

    public void doUpdate();

    public void doSave(String name);

    public String doFind();

}

 

 

4、Jdk_ProxyServiceImpl

package com.turtle.jdk;

/**
 * JDk的动态代理一定要满足实现接口的步骤
 */
public class Jdk_ProxyServiceImpl implements Jdk_ProxyService {

    @Override
    public void doUpdate() {
        System.out.println("进行更新操作");
    }

    @Override
    public void doSave(String name) {
        System.out.println("进行保存操作==="+name);
    }

    @Override
    public String doFind() {
        System.out.println("进行查询操作");
        return "SUCCESS";
    }
}

 

 

5、Jdk_MyInvocationHandler

package com.turtle.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

// 代理类
public class Jdk_MyInvocationHandler implements InvocationHandler {

    // 这个就是我们要代理的真实对象
    private Object target;
    // 构造方法,给我们要代理的真实对象赋初值
    public Jdk_MyInvocationHandler(Object target) {
        this.target = target;
    }

    /*
     *invoke方法方法参数解析
     *Object proxy:指被代理的对象。
     *Method method:要调用的方法
     *Object[] args:方法调用时所需要的参数
     *InvocationHandler接口的子类可以看成代理的最终操作类。
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("开始进行代理的增强");
        Object result= null;
        try{
            // 利用反射动态的来反射方法,这就是动态代理和静态代理的区别
            result = method.invoke(target,args);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            System.out.println("代理的增强完毕了");
        }
        return result;
    }
}

 

 

6、TestJdk

package com.turtle.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestJdk {
    public static void main(String[] args) {

        // 我们要代理的真实对象
        Jdk_ProxyService jdkProxyService = new Jdk_ProxyServiceImpl();
        // 我们要代理哪个真实对象,就将该对象传进去
        InvocationHandler invocationHandler = new Jdk_MyInvocationHandler(jdkProxyService);

        /*
         *newProxyInstance方法参数解析
         *ClassLoader loader:类加载器
         *Class<?>[] interfaces:得到全部的接口
         *InvocationHandler h:得到InvocationHandler接口的子类实例
         */
        Jdk_ProxyService jdkProxyServiceProxy = (Jdk_ProxyService)Proxy.newProxyInstance(jdkProxyService.getClass().getClassLoader(),jdkProxyService.getClass().getInterfaces(),invocationHandler);

        //jdkProxyServiceProxy.doFind();
        // jdkProxyServiceProxy.doSave("测试");
        jdkProxyServiceProxy.doUpdate();

    }
}

 

二、使用CgliB来完成动态代理

1、概述:

        使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,而且CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

2、代码结构、Jar包:

                                                                             技术图片  技术图片

 

3、Cglib_ProxyService,被代理对象

package com.turtle.cglib;

public class Cglib_ProxyService {

    /**
     * 该方法不能被子类覆盖,Cglib是无法代理final修饰的方法的
     */
    public final void doDel(){
        System.out.println("正在进行删除操作");
    }

    /**
     * 有返回值、无参数
     * @return
     */
    public String doFind(){
        System.out.println("正在进行查询操作");
        return "SUCCESS";
    }

    /**
     * 有参数、有返回值
     * @param name
     * @return
     */
    public String doSave(String name){
        System.out.println("正在进行保存操作"+name);
        return "SUCCESS";
    }

    /**
     * 无参数、无返回值
     */
    public void doUpdate(){
        System.out.println("正在进行修改操作");
    }
}

 

4、Cglib_MyMethodInterceptor,我们自定义的代理,对对象做增强操作

package com.turtle.cglib;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * 自己建立的AOP注入
 */
public class Cglib_MyMethodInterceptor implements MethodInterceptor {

    /**
     * @param o cglib生成的代理对象
     * @param method 被代理对象方法
     * @param objects 方法入参
     * @param methodProxy 代理方法
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        String result = null;
        // 通过方法签名来确定我们需要对哪些方法做增强操作
        if(methodProxy.getSignature().getName() == "doUpdate"){
            System.out.println("对doUpdate方法做前置增强");
            methodProxy.invokeSuper(o,objects);
            System.out.println("对doUpdate方法做后置增强");
        }
        if(methodProxy.getSignature().getName() == "doSave"){
            System.out.println("对doSave方法做前置增强");
            methodProxy.invokeSuper(o,objects);
            System.out.println("对doSave方法做后置增强");
        }
        if(methodProxy.getSignature().getName() == "doDel"){
            System.out.println("对doDel方法做前置增强");
            methodProxy.invokeSuper(o,objects);
            System.out.println("对doDel方法做后置增强");
        }
        if(methodProxy.getSignature().getName() == "doFind"){
            System.out.println("对doFind方法做前置增强");
            result = methodProxy.invokeSuper(o,objects).toString();
            System.out.println("对doFind方法做后置增强");
        }
        return result;
    }
}

 

5、Cglib_ProxyFactory,创建一个工厂来实例化我们的代理。

package com.turtle.cglib;

import net.sf.cglib.proxy.Enhancer;

/**
 * 将用来创建代理对象的操作放到简单工厂里面来实现
 */
public class Cglib_ProxyFactory<T> {

    public T createProxyObj(T obj){
        // 通过CGLIB动态代理获取代理对象的过程
        Enhancer enhancer = new Enhancer();
        // 设置enhancer对象的父类
        enhancer.setSuperclass(obj.getClass());
        // 设置enhancer的回调对象
        enhancer.setCallback(new Cglib_MyMethodInterceptor());
        // 创建代理对象
        return (T)enhancer.create();
    }
}

 

6、TestCglib,测试结果。

package com.turtle.cglib;

public class TestCglib {
    public static void main(String[] args) {
        // 取得工厂对象
        Cglib_ProxyFactory<Cglib_ProxyService> cglibProxyFactory = new Cglib_ProxyFactory<>();
        // 利用工厂来创建代理对象
        Cglib_ProxyService cglibProxyService = cglibProxyFactory.createProxyObj(new Cglib_ProxyService());

        // 通过代理对象调用目标方法

        // 无参数、无返回值的方法
        // cglibProxyService.doUpdate();

        // 有参数的方法
        // cglibProxyService.doSave("保存");

        // 有返回值的方法
        // String result = cglibProxyService.doFind();
        // System.out.println(result);

        // 被final修饰的方法
        cglibProxyService.doDel();
    }
}

 

三、总结

 

java-动态代理

标签:限制   actor   入参   code   增强   过程   tac   get   实例化   

原文地址:https://www.cnblogs.com/zhh19981104/p/11813586.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!