码迷,mamicode.com
首页 > 其他好文 > 详细

【面试】:阿里面试官问我设计模式——代理模式,我是这样回答的!

时间:2020-05-13 09:43:55      阅读:55      评论:0      收藏:0      [点我收藏+]

标签:cal   订单   llb   tcl   模式   ibm   子类   ack   string   

1.什么是代理模式? 为对象提供一种代理以控制对这个对象的访问。代理模式相当于:中介或者经纪人 ,代理类可以在被代理类的基础之上增加功能(扩展功能),比如日志记录和权限控制 ,这样被代理类隐藏起来了,比较安全。

1.代理模式实现方式有哪些?
静态代理和动态代理
2.静态代理是:需要程序员人为创建好代理类,缺点;如果被代理类很多的话,需要手写很多个代理类,代码会变得非常冗余。
3.静态代理实现方式有哪些?
1.通过继承2.实现接口

1.通过实现接口方式实现静态代理

1.定义共同接口

package com.mayikt.service;
public interface OrderService {

    /**
     * 共同抽象的方法
     */
    void order();
}

2.定义被代理类实现共同的接口

package com.mayikt.service.impl;

import com.mayikt.service.OrderService;

public class OrderServiceImpl implements OrderService {
    public void order() {
        System.out.println("执行订单业务逻辑代码");
    }
}

3.手写代理类OrderServiceProxy

package com.mayikt.service.proxy;

import com.mayikt.service.OrderService;
import com.mayikt.service.impl.OrderServiceImpl;
public class OrderServiceProxy implements OrderService {
    /**
     * 被代理对象
     */
    private OrderService orderService;

    public OrderServiceProxy(OrderService orderService) {
       this.orderService = orderService;
    }
    public void order() {
        System.out.println(">>>打印订单日志开始");
        orderService.order();
        System.out.println(">>>打印订单日志结束");
    }

}

4.测试

package com.mayikt.service;

import com.mayikt.service.cglib.proxy.CglibMethodInterceptor;
import com.mayikt.service.impl.OrderServiceImpl;
import com.mayikt.service.jdk.proxy.JdkInvocationHandler;
import com.mayikt.service.proxy.OrderServiceProxy;
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;

public class Client {
    public static void main(String[] args) {
       OrderService orderService = new OrderServiceProxy(new OrderServiceImpl());
       orderService.order();
    }
}

通过继承的方式实现静态代理

1.定义共同接口

package com.mayikt.service;
public interface OrderService {

    /**
     * 共同抽象的方法
     */
    void order();
}

2.定义被代理类

package com.mayikt.service.impl;

import com.mayikt.service.OrderService;

public class OrderServiceImpl implements  OrderService{
    public void order() {
        System.out.println("执行订单业务逻辑代码");
    }
}

3.手写代理类

package com.mayikt.service.proxy;

import com.mayikt.service.OrderService;
import com.mayikt.service.impl.OrderServiceImpl;

public class OrderServiceProxy extends OrderServiceImpl {

    public void order() {
        System.out.println(">>>打印订单日志开始");
        super.order();// 执行父类的order 方法OrderServiceImpl
        System.out.println(">>>打印订单日志结束");
    }

}

4、测试

package com.mayikt.service;

import com.mayikt.service.cglib.proxy.CglibMethodInterceptor;
import com.mayikt.service.impl.OrderServiceImpl;
import com.mayikt.service.jdk.proxy.JdkInvocationHandler;
import com.mayikt.service.proxy.OrderServiceProxy;
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;

public class Client  {
    public static void main(String[] args) {
        OrderService orderService = new OrderServiceProxy();
        orderService.order();
    }
}

动态代理

1.动态代理:不需要关心代理类, jvm运行的时候自动创建代理类,不需要手动创建。
2.动态代理实现方式有哪些?
jdk动态代理和cglib原理
3.jdk动态代理:jdk动态生成的代理类都是实现接口形式,所以被代理类必须实现接口(通过反射的方式实现)
cglib代理:通过asm字节码技术实现动态生成代理类,运行时动态的生成一个被代理类的子类
4.jdK动态代理要求被代理的类必须实现接口,当需要被代理的类没有实现接口时cglib代理是一个很好的选择
5.spring默认会使用JDK的动态代理,但是如果目标对象没有实现接口,则默认会采用CGLIB代理;

jdk实现动态代理

1.定义共同接口

package com.mayikt.service;
public interface OrderService {

    /**
     * 共同抽象的方法
     */
    void order();
}

2.定义被代理类实现共同的接口

package com.mayikt.service.impl;

import com.mayikt.service.OrderService;

public class OrderServiceImpl implements OrderService {
    public void order() {
        System.out.println("执行订单业务逻辑代码");
    }
}

3.创建生成动态代理类的类:JdkInvocationHandler

package com.mayikt.service.jdk.proxy;

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

public class JdkInvocationHandler implements InvocationHandler {
    /**
     * 被代理类对象 目标代理对象
     */
    private Object target;

    public JdkInvocationHandler(Object target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //执行方法前打印日志
        System.out.println(">>>jdk打印订单日志开始:proxy:"+proxy.getClass().toString());
        Object reuslt = method.invoke(target, args);// java的反射机制执行方法 执行目标对象的方法
        //执行方法后打印日志
        System.out.println(">>>jdk打印订单日志结束");
        return reuslt;
    }

    /**
     * 使用jdk动态代理创建代理类
     *
     * @param <T>
     * @return
     */
    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
}

4.测试

package com.mayikt.service;

import com.mayikt.service.cglib.proxy.CglibMethodInterceptor;
import com.mayikt.service.impl.OrderServiceImpl;
import com.mayikt.service.jdk.proxy.JdkInvocationHandler;
import com.mayikt.service.proxy.OrderServiceProxy;
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;

public class Client  {
    public static void main(String[] args) {
        // 1.使用jdk动态代理
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");//可以动态生成.class文件
        OrderService proxy = new JdkInvocationHandler(new OrderServiceImpl()).getProxy();
        proxy.order();

    }
}

使用cglib实现动态代理

     <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.12</version>
     </dependency>

2.定义被代理类

package com.mayikt.service.impl;

import com.mayikt.service.OrderService;

public class OrderServiceImpl {
    public void order() {
        System.out.println("执行订单业务逻辑代码");
    }
}

3.创建生成动态代理类的类:CglibMethodInterceptor

package com.mayikt.service.cglib.proxy;

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

import java.lang.reflect.Method;

public class CglibMethodInterceptor implements MethodInterceptor {
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println(">>>>cglib日志收集开始....");
        Object reuslt = proxy.invokeSuper(obj, args);
        System.out.println(">>>>cglib日志收集结束....");
        return reuslt;
    }
}

4.测试

package com.mayikt.service;

import com.mayikt.service.cglib.proxy.CglibMethodInterceptor;
import com.mayikt.service.impl.OrderServiceImpl;
import com.mayikt.service.jdk.proxy.JdkInvocationHandler;
import com.mayikt.service.proxy.OrderServiceProxy;
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;

public class Client  {
    public static void main(String[] args) {
        // 使用cglib动态代理
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");//可以动态生成class文件
        CglibMethodInterceptor cglibMethodInterceptor = new CglibMethodInterceptor();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(OrderServiceImpl.class);
        enhancer.setCallback(cglibMethodInterceptor);
        OrderServiceImpl orderServiceImpl = (OrderServiceImpl) enhancer.create();
        orderServiceImpl.order();

    }
}

总结:看完有什么不懂的话欢迎在下方留言评论,记得点个赞哦!

【面试】:阿里面试官问我设计模式——代理模式,我是这样回答的!

标签:cal   订单   llb   tcl   模式   ibm   子类   ack   string   

原文地址:https://blog.51cto.com/14801695/2494700

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