zoukankan      html  css  js  c++  java
  • 设计模式---JDK动态代理和CGLIB代理

    Cglig代理设计模式

    /*测试类*/

    package cglibProxy;

    import org.junit.Test;

    public class TestCglib {

      @Test
      public void test1(){
        CglibProxy cglibProxy=new CglibProxy();
        UserServiceImpl userServiceImpl = (UserServiceImpl)cglibProxy.createProxyInstance(new UserServiceImpl());
        userServiceImpl.addUser();
      }
    }

    /*代理类*/

    package cglibProxy;

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

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

    public class CglibProxy implements MethodInterceptor{

        //1.声明一个全局变量,被代理对象
        private Object target;

        //2.创建代理对象
        //参数是被代理对象
        public Object createProxyInstance(Object target){
        //赋值被代理对象
        this.target=target;
        Enhancer enhancer = new Enhancer();
        //设置代理对象的父类
        enhancer.setSuperclass(target.getClass());

        //设置回调函数
        //Callback是MethodInterceptor的父接口
        enhancer.setCallback(this);
        //返回创建出来的代理对象
        return enhancer.create();


      }

        //加工
        public Object intercept(Object proxy, Method method, Object[] arg,
          MethodProxy proxyMethod) throws Throwable {
          // TODO Auto-generated method stub


          //加工
          security();

        return proxyMethod.invoke(target, arg);

        }


        public void security(){
          System.out.println("进行权限控制");

        }
     }

    /*需要被代理对象*/

    package cglibProxy;

    public class UserServiceImpl{

      public void addUser() {

        System.out.println("增加了用户");
        // TODO Auto-generated method stub

      }

      public void deleteUser() {

        System.out.println("删除了用户");
        // TODO Auto-generated method stub

      }

      public void alterUser() {

        System.out.println("修改了用户");
        // TODO Auto-generated method stub

      }

      public void findUser() {
        System.out.println("查询了用户");
        // TODO Auto-generated method stub

      }

      public void security(){
        System.out.println("进行了权限控制111");

      }

    }

    JDK动态代理设计模式

    /*接口*/

    package jdkProxy;

    public interface IUserService {
      public void addUser();
      public void deleteUser();
      public void alterUser();
      public void findUser();
    }

    /*代理类*/

    package jdkProxy;

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

    //整个类是切面类
    public class JdkProxy implements InvocationHandler {

      //创建全局变量,被代理对象
      private Object target;

      //创建代理对象
      public Object createProxyInstance(Object target){
        //获取目标对象并赋值
        this.target=target;

        //根据目标对象创建对应的代理对象
        //三个参数,1.被代理对象的类加载器,2,被代理对象的所有接口,3,类型为InvocationHandler的对象,在本类中只有JdkProxy了
        //想要拿到类加载器首先拿到字节码,第三个参数this是指JdkProxy
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
        target.getClass().getInterfaces(), this);
      }


      //invoke这个方法是InvocationHandler的方法,实现需要重写
      //加工被代理对象
      //1.第一个参数是 刚创建的代理对象
      //2.第二个参数是需要被加工的方法,真实方法
      //3.第三个参数,需要被加工的方法的参数

      public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {

        //加工
        security();

        //执行被代理对象的方法,最终是由被代理对象的方法
        return method.invoke(target, args);
      }

      //通知(增强)方法
      public void security(){
        System.out.println("进行权限控制");

      }

    }

    /*测试类*/

    package jdkProxy;

    import org.junit.Test;

    public class TestJdkProxy {

      @Test
      public void tes1(){
        // IUserService userService=new UserServiceImpl();
        // userService.addUser();

        //创建代理对象,jdkProxy
        JdkProxy proxy=new JdkProxy();
        //执行创建代理对象的方法
        //参数就是被代理的对象
        //被代理对象要和代理对象接口要一致,要求被代理对象一定要实现接口

        //织入, weaver,就是创建一个代理对象,并调用被代理方法
       IUserService userService =(IUserService) proxy.createProxyInstance(new UserServiceImpl());
        userService.addUser();
      }
    }

    /*被代理对象*/

    package jdkProxy;

    public class UserServiceImpl implements IUserService {

      public void addUser() {

        System.out.println("增加了用户");
        // TODO Auto-generated method stub

      }

      public void deleteUser() {

        System.out.println("删除了用户");
        // TODO Auto-generated method stub

      }

      public void alterUser() {

        System.out.println("修改了用户");
        // TODO Auto-generated method stub

      }

      public void findUser() {
        System.out.println("查询了用户");
        // TODO Auto-generated method stub

      }

      public void security(){
        System.out.println("权限控制");

      }

    }

    动态代理:JDK动态代理和CGLIB代理的区别

    代理模式:代理类和被代理类实现共同的接口(或继承),代理类中存有指向被代理类的索引,实际执行时通过调用代理类的方法、实际执行的是被代理类的方法。

    而AOP,是通过动态代理实现的。

    一、简单来说:

      JDK动态代理只能对实现了接口的类生成代理,而不能针对类

      CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承)

    二、Spring在选择用JDK还是CGLiB的依据:

       (1)当Bean实现接口时,Spring就会用JDK的动态代理

       (2)当Bean没有实现接口时,Spring使用CGlib是实现

       (3)可以强制使用CGlib(在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)

    三、CGlib比JDK快?

      (1)使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

      (2)在对JDK动态代理与CGlib动态代理的代码实验中看,1W次执行下,JDK7及8的动态代理性能比CGlib要好20%左右。

  • 相关阅读:
    URAL 1998 The old Padawan 二分
    URAL 1997 Those are not the droids you're looking for 二分图最大匹配
    URAL 1995 Illegal spices 贪心构造
    URAL 1993 This cheeseburger you don't need 模拟题
    URAL 1992 CVS
    URAL 1991 The battle near the swamp 水题
    Codeforces Beta Round #92 (Div. 1 Only) A. Prime Permutation 暴力
    Codeforces Beta Round #7 D. Palindrome Degree hash
    Codeforces Beta Round #7 C. Line Exgcd
    Codeforces Beta Round #7 B. Memory Manager 模拟题
  • 原文地址:https://www.cnblogs.com/binghuaZhang/p/11566063.html
Copyright © 2011-2022 走看看