首页 > 技术文章 > java静态代理、动态代理、cglib代理

FivePointOne 2020-11-16 11:50 原文

首先定义一个接口:

public interface AdminControl {
    void find();
    void update();
    void add();
}

实现类:

public class AdminControlImpl implements AdminControl{
    public void find() {
        System.out.println("查询所有管理员信息");
    }

    public void update() {
        System.out.println("修改管理员信息");
    }

    public void add() {
        System.out.println("增加管理员信息");
    }
}

静态代理

public class AdminControlProxy implements AdminControl{
    private AdminControl adminControl;
    public AdminControlProxy(AdminControl adminControl){
        this.adminControl = adminControl;
    }
    public void find() {
        System.out.println("进入方法find");
        adminControl.find();
        System.out.println("退出方法find");
    }

    public void update() {
        System.out.println("进入方法update");
        adminControl.update();
        System.out.println("退出方法update");
    }
}

代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强.

静态代理缺点:

1.假设系统中需要代理的service过多,那么就会创建很多代理对象

2.假设代理的service方法改变,那么相应的代理对象也会改变

动态代理

  • proxy 代理对象
  • method 代理对象调用的方法
  • args 调用的方法中的参数
public class AdminControlInvocation implements InvocationHandler {
    private Object object;
    public AdminControlInvocation(Object object){
        this.object = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("进入方法"+method.getName());
        Object object = method.invoke(object,args);
        System.out.println("退出方法"+method.getName());
        return object;
    }
}

 

public class AdminMain {
    public static void main(String[] args) {

        AdminControlImpl target = new AdminControlImpl();
        AdminControl adminControl = new AdminControlProxy(target);
        AdminControl adminControl = (AdminControl) Proxy.newProxyInstance(AdminControlImpl.class.getClassLoader(),
                AdminControlImpl.class.getInterfaces(),
                new AdminControlInvocation(target));
        adminControl.find();
        adminControl.update();
        adminControl.add();
    }
}

 

假设代理的对象没有接口,那么就不能使用动态代理

cglib代理

首先引入依赖

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

代码

public class AdminControlCglibProxy implements MethodInterceptor {
    private Object object;
    public AdminControlCglibProxy(Object object){
        this.object = object;
    }
    public Object getProxyInstance(){
        Enhancer enhancer = new Enhancer();
        // 设置代理类的父类
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("进入方法"+method.getName());
        Object object = method.invoke(object,objects);
        System.out.println("退出方法"+method.getName());
        return object;
    }
}
public class AdminMain {
    public static void main(String[] args) {

        AdminControlImpl target = new AdminControlImpl();
        AdminControlImpl adminControl = (AdminControlImpl) new AdminControlCglibProxy(target).getProxyInstance();
        adminControl.find();
        adminControl.update();
        adminControl.add();
    }
}

 

对于一个没有接口的类,使用cglib代理,前提,该类必须可以被继承,方法不能为final、static。

cglib是采用动态创建子类的方法来代理

推荐阅读