静态代理和jdk动态代理,cglib

代理设计模式

什么是代理

增强一个对象的功能

java实现代理

静态代理

继承

代理对象继承目标对象,重写需要增强的方法;

缺点:会代理类过多,非常复杂

public interface UserService {
    void test1();

    String test2(String str);
}
public class UserServiceImpl implements UserService {
    @Override
    public void test1() {
        System.out.println("UserServiceImpl---test1");

    }

    @Override
    public String test2(String str) {

        System.out.println("UserServiceImpl---test2");

        return str;
    }
}
public class UserServiceLog extends UserServiceImpl {
    @Override
    public void test1() {
        System.out.println("log---test1");
        super.test1();

    }

    @Override
    public String test2(String str) {
        System.out.println("log---test2");
        return super.test2(str);
    }
}
public class UserServiceLogAndCheck extends UserServiceLog {
    @Override
    public void test1() {
        System.out.println("check---test1");
        super.test1();

    }

    @Override
    public String test2(String str) {
        System.out.println("check---test2");
        return super.test2(str);
    }
}
public class TestExtendsProxy {
    public static void main(String[] args) {
        UserService userService = new UserServiceLog();
        userService.test1();//1
        System.out.println(userService.test2("hello"));//2

        UserService userService2 = new UserServiceLogAndCheck();
        userService2.test1();//3
        System.out.println(userService2.test2("world"));//4
    }
}
他们的单独执行结果分别为
1:
log---test1
UserServiceImpl---test1
2:
log---test2
UserServiceImpl---test2
hello
3:
check---test1
log---test1
UserServiceImpl---test1
4:
check---test2
log---test2
UserServiceImpl---test2
world

显然,我们每写一个代理类,他的代理方法的执行顺序就已经固定了
比如,在现有的代码中,我们想只进行check代理,无法实现,必须再新建一个类,继承UserServiceImpl,对他进行代理
会产生非常多的类

聚合

目标对象和代理对象实现同一个接口,代理对象当中要包含目标对象。

缺点:也会产生类爆炸,只不过比继承少一点点

public interface UserService {
    void test1();

    String test2(String str);
}
public class UserServiceImpl implements UserService {
    @Override
    public void test1() {
        System.out.println("UserServiceImpl---test1");

    }

    @Override
    public String test2(String str) {

        System.out.println("UserServiceImpl---test2");

        return str;
    }
}
public class UserServiceLog implements UserService {

    private UserService userService;

    public UserServiceLog(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void test1() {
        System.out.println("log--------test1");
        userService.test1();
    }

    @Override
    public String test2(String str) {
        System.out.println("log--------test2");
        return userService.test2(str);
    }
}
public class UserServiceCheck implements UserService {

    private UserService userService;

    public UserServiceCheck(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void test1() {
        System.out.println("check---test1");
        userService.test1();
    }

    @Override
    public String test2(String str) {
        System.out.println("check---test2");
        return userService.test2(str);
    }
}
public class TestAggregationProxy {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        UserService userServiceLog = new UserServiceLog(userService);
        userServiceLog.test1();//1
        System.out.println(userServiceLog.test2("hello"));//2

        UserServiceCheck userServiceCheck = new UserServiceCheck(userServiceLog);
        userServiceCheck.test1();//3
        System.out.println(userServiceCheck.test2("world"));//4
    }
}
他们的单独执行结果分别为
1:
log--------test1
UserServiceImpl---test1
2:
log--------test2
UserServiceImpl---test2
hello
3:
check---test1
log--------test1
UserServiceImpl---test1
4:
check---test2
log--------test2
UserServiceImpl---test2
world

显然,聚合相对于通过继承实现的静态代理,会灵活一点
比如,现有log和check两个代理类,我们可以实现只log代理,只check代理,先log再check,先check再log
当然也会产生很多类

动态代理

jdk动态代理

public interface UserService {
    void test1();

    String test2(String str);
}
public class UserServiceImpl implements UserService {
    @Override
    public void test1() {
        System.out.println("UserServiceImpl---test1");

    }

    @Override
    public String test2(String str) {

        System.out.println("UserServiceImpl---test2");

        return str;
    }
}
public class MyInvocationHandler implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("start-----" + method.getName());
        if (null != args) {
            args[0] = "被改的入参";
        }
        Object invoke = method.invoke(target, args);
        System.out.println("end----" + method.getName());
        return invoke;
    }

    public Object getProxy() {
        return Proxy.newProxyInstance(MyInvocationHandler.class.getClassLoader(), target.getClass().getInterfaces(), this);
    }
}
public class TestDynamicProxy {
    public static void main(String[] args) {
    	// 开启保存class文件,可以生成com.sun.proxy.$Proxy0.class
		System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
        UserService userService = new UserServiceImpl();
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(userService);
        UserService proxy = (UserService) myInvocationHandler.getProxy();
        proxy.test1();//1
        System.out.println(proxy.test2("hello"));//2
    }
}
他们的单独执行结果分别为
1:
start-----test1
UserServiceImpl---test1
end----test1
2:
start-----test2
UserServiceImpl---test2
end----test2
被改的入参

cglib

public class UserServiceImpl{
    public void test1() {
        System.out.println("UserServiceImpl---test1");
    }

    public String test2(String str) {
        System.out.println("UserServiceImpl---test2");
        return str;
    }
}
public class CglibProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz) {
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("start----");
        Object invoke = methodProxy.invokeSuper(o, objects);
        System.out.println("end----");
        return invoke;
    }
}
public class TestCglibProxy {
    public static void main(String[] args) {
        // 设置生成的class文件保存路径
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/ex-zhuchen001/Desktop");
        CglibProxy cglibProxy = new CglibProxy();
        UserServiceImpl proxy = (UserServiceImpl) cglibProxy.getProxy(UserServiceImpl.class);
        proxy.test1();
    }
}
执行结果为:
start----
UserServiceImpl---test1
end----

代理class文件的生成

在main方法中先执行如下代码

// jdk动态代理
// 开启保存class文件,可以生成com.sun.proxy.$Proxy0.class
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");

// cglib动态代理
// 设置生成的class文件保存路径
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/my/Downloads");

jdk动态代理和cglib的异同

jdk动态代理是动态的生成一个java类,实现目标类所实现的接口,并且在其中调用目标类中的方法,所以必须有接口的类才能被代理.并且代理类和目标类都是实现同一个接口,他们并不能相互转换.

cglib实际上是通过继承目标类来生成代理类,所以无论是否有接口,都可以通过cglib来实现动态代理.由于代理类的父类是目标对象,所以代理类是可以赋值给目标对象的,自然如果目标对象有接口,代理对象也是可以赋值给接口的.

CGLIB 动态代理中生成的代理类的字节码相比 JDK 来说更加复杂。

JDK 使用反射机制调用目标类的方法,CGLIB 则使用类似索引的方式直接调用目标类方法,所以 JDK 动态代理生成代理类的速度相比 CGLIB 要快一些,但是运行速度比 CGLIB 低一些,并且 JDK 代理只能对有接口的目标对象进行代理。

发布了37 篇原创文章 · 获赞 1 · 访问量 1060

猜你喜欢

转载自blog.csdn.net/zhuchencn/article/details/103467483