美文网首页alreadyspringjs css html
Spring底层核心原理解析

Spring底层核心原理解析

作者: 马小莫QAQ | 来源:发表于2022-08-25 16:04 被阅读0次

    本章会把Spring中的Bean生命周期进行较为详细的讲解

    一、Bean的创建生命周期

    • 通过推断构造方法来实例化一个对象
    • 对该对象进行依赖注入(属性赋值)
    • 依赖注入后,Spring会判断该对象是否实现了BeanNameAware接口、BeanClassLoaderAware接口、BeanFactoryAware接口,如果实现了,就表示当前对象必须实现该接口中所定义的setBeanName()、setBeanClassLoader()、setBeanFactory()方法,那Spring就会调用这些方法并传入相应的参数(Aware回调
    • 初始化前(@PostConstruct)
    • 初始化(继承InitializingBean类)
    • 初始化后(AOP)
    • 获取到代理对象

    二、Spring中是通过什么方式创建对象的

    在java语言中肯定是通过某个类去创建对象的, 下面是实例代码

    public static void main(String[] args) {
        // 创建一个Spring对象
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        // 创建对象
        NingxuanService ningxuanService = (NingxuanService)context.getBean("ningxuanService");
        // 执行方法
        ningxuanService.test();
    }
    

    一共分为三步走:

    • 解析Appconfig类, 获取扫描路径, 获取Bean对象
    • 扫描包下的所有类文件的注解, 如果发现 @Component, @Service, @Bean等注解的时候就会将这些注解给记录下来, 存到一个Map中
    • Spring会根据相应的规则生成对应的BeanName作为map的key, value是当前类

    这个时候调用 context.getBean("BeanName")的时候就会获取到对应的实体类, 从而去创建对象

    三、Bean生命周期详解

    首先, 我们新建一个Config类, 设定好包扫描路径同时开启AOP

    @ComponentScan("com.ningxuan")
    @EnableAspectJAutoProxy
    public class AppConfig {
        @Bean
        public NingxuanService ningxuanService(){
            return new NingxuanService();
        }
    }
    

    推断构造方法

    Spring在基于某个类生成Bean的时候, 会通过该类的构造方法去实例化一个对象, 但是如果这个类拥有多个构造方法的时候就会进入以下的判断

    • 只有一个构造方法, 那么不管这个构造犯法是有参的还是无参的都会使用这个构造方法
    • 如果存在多个构造方法
      • 在多个构造犯法中, 若存在无参构造方法, 则默认使用无参构造犯法
        • 若该有参构造方法上有使用 @Autowired注解, 则使用有参构造
      • 若多个构造方法皆为有参构造
        • 若构造方法上都没有加 @Autowired注解, 则报错
        • 若有某一个构造方法上加了 @Autowired注解, 则使用该构造方法
        • 若存在多个构造方法上交了 @Autowired注解, 则报错

    Spring会根据入参的类型和名字去Spring中找Bean对象:

    • 先根据入参类型找, 若只找到一个, 那就直接用来作为入参
    • 如果根据类型找到多个, 则在根据入参名字来确定唯一的一个
    • 最终如果没有找到, 则报错

    确定用哪个构造方法, 确定入参的Bean对象, 这个古城就叫做推断构造方法

    依赖注入

    通过推断构造方法得到一个对象后, Spring会判断该对象中是否存在被 @Autowired 注解了的属性, 把这些属性找出来并由Spring进行赋值

    初始化前

    被 @PostConstruct 注解标注的方法, 是为该bean初始化前执行的方法, 具体如下

    @Component()
    public class NingxuanService{
    
        // 初始化前执行
        @PostConstruct
        public void after(){
            System.out.println("初始化前");
        }
    
        public void test(){
            System.out.println("执行方法: 宁轩");
        }
    }
    

    初始化

    想要一个方法在被Spring创建对象初始化时执行, 则要将这个类继承 InitializingBean 类, 并实现 afterPropertiesSet 方法, 且要抛出异常, 具体如下

    @Component()
    public class NingxuanService implements InitializingBean {
    
        // 初始化前执行
        @PostConstruct
        public void after(){
            System.out.println("初始化前");
        }
    
        public void test(){
            System.out.println("执行方法: 宁轩");
        }
    
        // 初始化执行
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("初始化");
        }
    }
    

    AOP

    想要执行AOP, 老规矩, 在扫描类上使用注解 @EnableAspectJAutoProxy 进行标注, , 并且新建一个aop类, 使用 @Aspect和@Component 注解标注, 本次测试采用了 AOP 中的前置执行和后置执行, 具体如下:

    @Aspect
    @Component
    public class TestAop {
        @After("execution(public void com.ningxuan.demo.service.NingxuanService.test())")
        public void TestAfter(JoinPoint joinPoint){
            System.out.println("方法执行后");
        }
        @Before("execution(public void com.ningxuan.demo.service.NingxuanService.test())")
        public void TestVefore(JoinPoint joinPoint){
            System.out.println("方法执行前");
        }
    }
    

    执行测试

    根据以上的代码, 我们执行 main 方法, 可以得到以下测试结果

    作者:宁轩
    链接:https://juejin.cn/post/7134488068111171597
    来源:稀土掘金

    相关文章

      网友评论

        本文标题:Spring底层核心原理解析

        本文链接:https://www.haomeiwen.com/subject/fzfzgrtx.html