专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

Spring源码分析-二、合成类

什么是合成类

合成类, 指的是不能通过源代码看到的类, 而是由编译器自动生成的类, 依据Spring的描述, 合成类指的是不是通过应用程序创建出来的
类, 其实这个合成类应该算是Java语言知识中的一部分

演示合成类

public class UserService  {
    public void test1 () {
       new UserServiceInner();
    }

    public static class UserServiceInner {
        public UserServiceInner () {

        }
    }
}

分析: 
    可以看到, 我们在UserService中有一个静态内部类UserSerivceInner, 我们显示的指定了其默认构造方法, 注意, 这里我们显示指定
    成了pulic修饰, 然后我们在test1方法中创建了内部类的实例, 此时我们编译这个文件会发现, 在编译后的class文件夹下, 出现了
    两个class文件, 分别是UserService$UserServiceInner.class以及UserService.class

public class UserService  {
    public void test1 () {
       new UserServiceInner();
    }

    public static class UserServiceInner {
        private UserServiceInner () {

        }
    }
}

分析:
    此时我们将这个静态内部类的构造方法设置成了私有的访问权限, 但是我们可以看到在test1方法中还是能够对该类进行实例化的, 
    在Java中, 被private修饰的方法, 仅仅只能被当前类访问, 但是此时却出现了private修饰的方法被其他类访问了, 在Java中是通
    过编译器额外生成一个构造方法来实现的, 并且这个额外的构造方法还必须有参数, 那么这个参数应该是什么呢?其实可以是一个额外
    生成的类就好了, 换句话说, 编译器会做如下的事情

<1> 创建一个额外的类, 比如UserServiceInner$1, 即在UserService中创建一个额外的静态类, 此时代码会变成
public class UserService  {
    public void test1 () {
       new UserServiceInner();
    }

    public static class UserServiceInner {
        private UserServiceInner () {

        }
    }

    public static class UserService$1 {}
}

<2> 在UserServiceInner中额外的增加一个构造方法, 该构造方法接收一个UserService$1类型的参数, 因为这个类是由编译器创建的,
    所以放入一个该类的实例也是很简单的, 此时代码变成:
public class UserService  {
    public void test1 () {
       new UserServiceInner();
    }

    public static class UserServiceInner {
        private UserServiceInner () {

        }

        public UserServiceInner (UserService$1 obj) {

        }
    }

    public static class UserService$1 {}
}

<3> 将test1方法中调用的构造方法改成编译器生成的构造方法, 并手动生成一个UserService$1类的实例, 此时代码变为
public class UserService  {
    public void test1 () {
       new UserServiceInner( new UserService$1() );
    }

    public static class UserServiceInner {
        private UserServiceInner () {

        }

        public UserServiceInner (UserService$1 obj) {

        }
    }

    public static class UserService$1 {}
}

分析: 由上述过程, 就成功的创建了默认构造方法为private的UserServiceInner的类的实例, 实际上, Java中也确实是这样来实现的,
      如果想要看到上面的效果, 可以试着编写一个测试用例来看看, 需要注意的是, 如果要看到这个$1结尾的类, 需要去编译生成的
      class文件夹中才能看到, 更需要注意的是, 如果要看到实际的内部代码的情况, 需要通过javap -cv xxx来看到

总结

在上述的例子中, UserService$1这个类就是一个合成类, 它不能通过源代码来看到, 是由编译器生成的类, 不是通过应用程序生成的类,
之所以对合成类进行解释, 是因为在Spring中, 对于一个合成类, 是不会扫描进来的, 并且在AOP进行动态代理的时候, 对于合成类是不会
进行代理的, 因为这个是由编译器优化生成的类, 不是程序员希望出现的, 所以在Spring中很多操作都会在非合成类的情况下才能继续进
行下去, 并且在Java中也有代码来确定一个类是否为合成类, 即: Class对象的isSynthetic方法, 当我们调用一个合成类的该方法时会
返回true, 大家可以通过ClassLoader的loadClass方法手动加载合成类并判断来证明这个结论

文章永久链接:https://tech.souyunku.com/36527

未经允许不得转载:搜云库技术团队 » Spring源码分析-二、合成类

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们