• 设计模式---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%左右。

  • 相关阅读:
    转载--详解tomcat配置
    MongoDB@入门一
    面试@单例模式
    单点登录系统(一)
    SublimeText3 初探(工欲善其事,必先利其器)
    UEFI+GPT 修复 win10启动
    悟空模式-java-建造者模式
    悟空模式-java-原型模式
    悟空模式-java-单例模式
    悟空模式-java-抽象工厂模式
  • 原文地址:https://www.cnblogs.com/binghuaZhang/p/11566063.html
Copyright © 2020-2023  润新知