结构型之代理模式

序言

  代理模式可以实现对被代理对象的间接控制,可以对被代理对象的方法进行增强,她不重写原有的方法。
代理模式基本分为3类:

  1. jdk静态代理: 1个代理类只能代理1个类,局限性较大。
  2. jdk动态代理: 1个代理类能代理多个类,要求被代理类必须要有接口,利用了反射,效率比较低。
  3. cglib动态代理:1个代理类能代理多个类,被代理类不需要有接口,效率较高,不能代理final的类和方法

1. jdk静态代理模式

套路:

  1. 代理类要实现被代理类的接口,使代理类的方法与被代理类的保持一致。
  2. 代理类要加入一个被代理类的委托对象,由客户端初始化。
  3. 添加私有的增强方法。
/**
 * 登录接口
 */
public interface LoginService {
    public void login();
}
/**
 * 登录接口代理对象
 */
public class LoginServiceProxy implements LoginService{
    private LoginService loginService;

    public LoginServiceProxy(LoginService loginService){
        this.loginService = loginService;
    }
    public void login() {
        preLogin();
        loginService.login();
        postLogin();
    }
    private void preLogin(){
        System.out.println("=====登录前认证校验=====");
    }
    private void postLogin(){
        System.out.println("=====登录后日志记录=====");
    }

}
/**
 * 登录接口实现类
 */
public class LoginServiceImpl implements LoginService{
    public void login() {
        System.out.println("正在登录...");
    }
}
/**
 * jdk静态代理测试
 */
public class JdkStaticProxyTest {

    @Test
    public void testJdkStaticProxy(){
        LoginServiceProxy loginServiceProxy = new LoginServiceProxy(new LoginServiceImpl());
        loginServiceProxy.login();
    }
}

2. jdk动态代理模式

/**
 * 登录接口
 */
public interface LoginService {
    public void login();
}
/**
 * 登录接口实现类
 */
public class LoginServiceImpl implements LoginService {
    public void login() {
        System.out.println("正在登录...");
    }
}
/**
 * 登录接口代理对象
 */
public class ServiceInvocationHandler implements InvocationHandler {

    //被代理对象
    private Object target;

    public ServiceInvocationHandler(Object object){
        this.target = object;
    }

    private void preOperation(){
        System.out.println("=====执行前校验=====");
    }
    private void postOperation(){
        System.out.println("=====执行后记录日志=====");
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        preOperation();
        Object result = method.invoke(target, args);
        postOperation();
        return result;
    }

    public Object getProxy() throws Throwable {

        return Proxy.newProxyInstance(Thread.currentThread()
                .getContextClassLoader(), this.target.getClass()
                .getInterfaces(), this);
    }
}
/**
 * jdk静态代理测试
 */
public class JdkDynamicProxyTest {

    @Test
    public void testJdkStaticProxy() throws Throwable {
        LoginService proxy = (LoginService) new ServiceInvocationHandler(new LoginServiceImpl()).getProxy();
        proxy.login();
        System.out.println(proxy.getClass());
    }
}

3. cglib动态代理模式

/**
 * 登录类
 */
public class LoginServiceImpl{
    public void login() {
        System.out.println("正在登录...");
    }
}
/**
 * 登录接口代理对象
 */
public class LoginServiceProxy implements MethodInterceptor{

    private Object target;

    public LoginServiceProxy(Object obj){
        this.target = obj;
    }

    public Object getInstance(){

        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this); //设置回调方法
        return enhancer.create(); //创建代理对象
    }

    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        preOpteration();
        Object result = methodProxy.invokeSuper(o, objects);
        postOpteration();
        return result;
    }

    private void preOpteration(){
        System.out.println("=====执行前校验=====");
    }
    private void postOpteration(){
        System.out.println("=====执行后记录日志=====");
    }

}
/**
 * cglib动态代理测试
 */
public class CglibProxyTest {
    
    @Test
    public void testCglibProxy(){
        LoginServiceImpl loginServiceProxy = (LoginServiceImpl) new LoginServiceProxy(new LoginServiceImpl()).getInstance();
        loginServiceProxy.login();
    }
}

后记

posted @ 2017-08-10 16:19  吃不了兜着走  阅读(116)  评论(0编辑  收藏  举报