JAVA基础——代理模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA基础——代理模式相关的知识,希望对你有一定的参考价值。

实现java代理一般分为静态代理和动态代理(jdk代理和cglib代理)

代理模式

技术分享图片

简单的说就是对原有的业务进行代理,外界通过代理访问真实对象,代理类似现在的中介机构,房产中介就是一个代理,代理房东,租户只要找到代理而无须关心房东是谁,代理能在房东的基础上增强房东的行为。

代理模式代码

JAVA静态代理

业务接口

package com.rrg.proxy.jdk.staticProxy;
/**
 * 
 * @author abc
 *
 */
public interface Count {
    /**
     * 查询余额
     */
    public void queryMoney();
    
    /**
     * 转账
     */
    public void transferMoney();
}

 

业务实现类

package com.rrg.proxy.jdk.staticProxy;

public class CountImpl implements Count {

    
    public void queryMoney() {
        System.out.println("queryMoney()");
    }

    public void transferMoney() {
        System.out.println("transferMoney()");
    }

}

 

代理

package com.rrg.proxy.jdk.staticProxy;
/**
 * java静态代理
 * @author abc
 *
 */
public class JDKStaticProxy implements Count {

    private CountImpl countImpl;
    
    public JDKStaticProxy(CountImpl countImpl) {
        this.countImpl = countImpl;
    }

    public void queryMoney() {
        System.out.println("===开始查询===");
        countImpl.queryMoney();
        System.out.println("===查询结束===");
    }

    public void transferMoney() {
        System.out.println("===开始转账===");
        countImpl.transferMoney();
        System.out.println("===转账成功===");
    }

}

 

测试

/**
     * jdk静态代理
     */
    @Test
    public void test1(){
        CountImpl impl = new CountImpl();
        JDKStaticProxy proxy = new JDKStaticProxy(impl);
        proxy.queryMoney();
        System.out.println();
        proxy.transferMoney();
    }

 

JAVA动态代理

 

模拟业务方法接口UserService.java

package com.rrg.proxy.jdk.dynamic;
/**
 * 创建业务接口
 * @author abc
 *
 */
public interface UserService {
    /**
     * 新增人员
     */
    public void add();
}

业务方法实现UserServiceImpl.java

package com.rrg.proxy.jdk.dynamic;

public class UserServiceImpl implements UserService {

    public void add() {
        System.out.println("add()");
    }

}

代理类,负责处理代理

package com.rrg.proxy.jdk.dynamic;

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

public class JDKDynamicHandler implements InvocationHandler {

    private UserService userService;
    
    public JDKDynamicHandler(UserService userService) {
        super();
        this.userService = userService;
    }
    
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        
        System.out.println("===添加人员处理===");
        Object result = method.invoke(userService, args);
        System.out.println("===添加人员完毕===");
        
        return result;
    }

    public Object getProxy() {
        //通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用
        //创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类
        
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), this.userService.getClass().getInterfaces(), this);
    }
}

测试

/**
     * jdk动态代理
     */
    @Test
    public void test2() {
        UserService userService = new UserServiceImpl();
        JDKDynamicHandler handler = new JDKDynamicHandler(userService);
        UserService proxy = (UserService) handler.getProxy();
        proxy.add();
    }

 

 

CGLIB动态代理

不需要接口直接代理实现类

业务实现类

package com.rrg.proxy.cglib;

public class BookFacadeImpl {

    /**
     * 添加图书
     */
    public void addBook() {
        System.out.println("addBook()");
    }
}

代理

package com.rrg.proxy.cglib;

import java.lang.reflect.Method;

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

public class BookFacadeCglib implements MethodInterceptor {

    private BookFacadeImpl bookService;
    
    public Object getInstance(BookFacadeImpl bookService) {
        Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类
        enhancer.setSuperclass(this.bookService.getClass());  //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
        //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
        enhancer.setCallback(this); 
        // 创建动态代理类对象并返回  
        return enhancer.create(); 
    }
    //回调方法
    public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("===准备添加图书===");
        methodProxy.invokeSuper(object, args);
        System.out.println("===完成添加图书===");
        return null;
    }

}

测试

/**
     * cglib动态代理
     */
    @Test
    public void test3() {
        BookFacadeImpl bookService = new BookFacadeImpl();
        BookFacadeCglib cglib = new BookFacadeCglib();
        BookFacadeImpl bookCglib = (BookFacadeImpl) cglib.getInstance(bookService);
        bookCglib.addBook();
    }

总结


(1)静态代理是在编译时创建一个业务代理类,通过代理访问同名方法,实现对原方法的包装(代理类继承业务类)
(2)JDK动态代理通过接口的方法名,在动态的代理类调用同名业务方法,实现对原方法的包装(实现InvocationHandler)
(3)CGLIB动态代理通过继承业务类,创建出一个增强的业务类(实现MethodInterceptor)

代理是一个AOP思想的体现,切面编程对业务方法的前后进行增强

在Spring的AOP编程中:
  如果加入容器的目标对象有实现接口,用JDK代理
  如果目标对象没有实现接口,用Cglib代理






以上是关于JAVA基础——代理模式的主要内容,如果未能解决你的问题,请参考以下文章

Spring之代理模式

Java设计模式之代理模式

java基础 代理机制

java基础 代理机制

Java动态代理

Java动态代理