JAVA代理

静态代理和动态代理区别:
我们根据加载被代理类的时机不同,将代理分为静态代理和动态代理。①如果我们在代码编译时就确定了被代理的类是哪一个,那么就可以直接使用静态代理;②如果不能确定,那么可以使用类的动态加载机制,在代码运行期间加载被代理的类这就是动态代理,比如RPC框架和Spring AOP机制

代理的优点是在不改变这个方法的前提下去丰富他。这样老功能试用原来的方法也不会有问题,新功能通过代理丰富了原来的方法被广泛试用。

动态代理

新建一个开发者接口,开发者他会开发code,他会调试debug

public interface Developer {
    void code();
    void debug();
}

新建一个java开发者来实现开发者接口里的code、debug方法

@Data
public class JavaDeveloper implements Developer {
    String name;

    public JavaDeveloper(String name) {
        this.name = name;
    }

    @Override
    public void code(){
        System.out.println("a code man");
    }

    @Override
    public void debug(){
        System.out.println("a debug man");
    }
}

进行动态代理使用java开发者开发项目

@RunWith(SpringRunner.class)
@SpringBootTest(classes = AdminApplication.class)
public class ProxyTest {

    @Test
    public void NoProxyTest(){
        JavaDeveloper Jack = new JavaDeveloper("Jack");
        Jack.code();
        Jack.debug();
        //打印结果
//        a code man
//        a debug man
    }

    @Test
    public void ProxyTest(){
        JavaDeveloper Jack = new JavaDeveloper("Jack");
        Developer jackProxy = (Developer) Proxy.newProxyInstance(
        		Jack.getClass().getClassLoader(),
                Jack.getClass().getInterfaces(),
                (proxy, method, args) -> {
            if (method.getName().equals("code")){
                System.out.println("Jack proxy code!!");
                method.invoke(Jack, args);
            }
            if (method.getName().equals("debug")){
                System.out.println("Jack proxy debug!!");
                return null;
            }
            return null;
        });
        jackProxy.code();
        jackProxy.debug();
        //打印结果
//        Jack proxy code!!
//                a code man
//        Jack proxy debug!!
    }
}

刚开始把Developer写成了类,JavaDeveloper继承。报错如下:

java.lang.ClassCastException: com.sun.proxy.$Proxy12 cannot be cast to Developer

原因:
对于Spring AOP 采用两种代理方法,一种是常规JDK,一种是CGLIB,当代理对象实现了至少一个接口时,默认使用JDK动态创建代理对象,当代理对象没有实现任何接口时,就会使用CGLIB方法。

解决方法:
Java api代理机制求被代理类必须要实现某个接口。将代理对象转换成接口。

静态代理

写一个知道代理类的静态代理实现类

public class StaticProxyTest implements Developer{

    JavaDeveloper javaDeveloper;

    public StaticProxyTest(JavaDeveloper javaDeveloper) {
        this.javaDeveloper = javaDeveloper;
    }

    @Override
    public void code() {
        System.out.println("ProxyTest sayHello begin");
        //在代理类的方法中 间接访问被代理对象的方法
        javaDeveloper.code();
        System.out.println("ProxyTest sayHello end");
    }

    @Override
    public void debug() {
        System.out.println("ProxyTest sayHello begin");
        //在代理类的方法中 间接访问被代理对象的方法
        javaDeveloper.debug();
        System.out.println("ProxyTest sayHello end");
    }
}

 @Test
    public void staticProxyTest(){
        JavaDeveloper javaDeveloper = new JavaDeveloper("Jack");
        StaticProxyTest proxyTest = new StaticProxyTest(javaDeveloper);
        proxyTest.code();
        proxyTest.debug();
    }
    //打印
//    ProxyTest sayHello begin
//    a code man
//    ProxyTest sayHello end
//    ProxyTest sayHello begin
//    a debug man
//    ProxyTest sayHello end

参考:详解java动态代理机制以及使用场景(一)

上一篇:JavaScript高级知识


下一篇:Mysql 8 - 检查约束