Bean生命周期底层原理

生命不息,写作不止

持续踏上学习之路,学之共享笔记

总有一天我也能像各位大佬相同

一个有梦有戏的人 @盛开吧德德

共享学习心得,欢迎纠正,大家一同学习生长!

【Spring系列】- Bean生命周期底层原理

前语

上次学到着手模仿Spring底层完成,简单学习了一下Spring,对spring有所了解,接着就来剖析spring中bean的生命周期的步步流程。

流程

接下来会依据Bean生命周期一步一步去学习,spring在创立bean目标的过程中,仍是做了许多的操作,从依靠注入,经过初始化以及前后操作,最终创立了bean目标放入Map单例池,关于多例是不放进去的。

【Spring系列】- Bean生命周期底层原理

本次试验运用的pom依靠坐标如下

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.3.15</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aspects</artifactId>
  <version>5.3.15</version>
</dependency>

依靠注入

首要是依据无参结构办法去获取目标,经过这个类获取一切字段,在来判别是否有Autowired注解,在给这个属性去赋值。

UserService userService1 = new UserService();
for (Field field : userService1.getClass().getDeclaredFields()) {
    if (field.isAnnotationPresent(Autowired.class)) {
        field.set(userService1, ???);
    }
}

初始化前履行办法

经过目标获取一切办法,咱们在需求履行的办法上运用PostConstruct注解,然后就只需求遍历这些办法,去判别是否含有这个注解,在运用invoke去履行办法。

for (Method method : userService1.getClass().getMethods()) {
    if (method.isAnnotationPresent(PostConstruct.class)) {
        method.invoke(userService1, null);
    }
}

初始化

除了运用PostConstruct注解去履行办法,还有一种办法是经过去完成InitializingBean接口,并且需求完成其未完成的办法afterPropertiesSet。

那么目标是如何知道在spring中会有afterPropertiesSet这个办法呢?能够经过反射判别是否有这个办法,有的话就直接履行。在spring中,他是采用去判别目标是否有完成InitializingBean这个类,有的话会强转成这个类,再去履行这个类的办法

推断结构办法底层原理

假如有多个结构办法,回去寻找是否有无参的,找到了,就直接运用,没找到就会报错。假如是运用了多个结构办法,能够运用Autowired去告知spring需求运用那个结构办法。假如在结构办法里需求一个bean目标,那么spring会去map单例池中去查找相应的bean目标,假如没找到,就会去创立bean目标,但假如是多例bean的话,就不需求查找,直接创立一个目标。 当咱们运用结构办法获取bean目标时,一般是经过类上运用Component注解去界说一个首位字母小写的bean目标,也能够是经过Bean注解,去创立不同bean名的相同类型的bean目标。

如下代码,在装备中增加两个bean目标,包含类上自己生成的总共三个bean目标。分别为{roleServiceroleService1roleService2}。这三个的类型相同,可是目标是不同的,姓名不同,bean目标就不同。

@ComponentScan("com.lyd")
public class ApplicationConfig {
    @Bean
    public RoleService roleService1() {
        return new RoleService();
    }
    @Bean
    public RoleService roleService2() {
        return new RoleService();
    }
}

当运用其中一个beanName都是能够的

@Component
public class UserService {
    private RoleService roleService;
    public UserService(RoleService roleService1) {
        this.roleService = roleService1;
    }
    public void test(){
        System.out.println(roleService);
    }
}

可是假如运用的不是上面三个其中之一,就会报错。可是能看到他找到了三个。

【Spring系列】- Bean生命周期底层原理

AOP – 动态署理

运用AOP便是需求运用署理目标,但是署理目标与第一次的目标是不相同的。 首要界说一个aop切面

@Aspect
@Component
public class AopAspect {
    @Before("execution(public void com.lyd.service.UserService.test())")
    public void beanBefore(JoinPoint joinPoint) {
        System.out.println("before");
    }
}

在装备类中标上注解 @EnableAspectJAutoProxy 开启切面,这样切面就会完成了。再来debug调用userService的test办法,能够观察到,获得的目标是CGLIB署理的目标

【Spring系列】- Bean生命周期底层原理
并且能看到里面的roleService是没有值的。可是从运行结果来看,先走了切面,最终的roleService是有值的。
【Spring系列】- Bean生命周期底层原理
但是这都是因为署理类是父子级联系来完成的。接下来一步一步剖析。
【Spring系列】- Bean生命周期底层原理
spring经过署理目标,便是为了能够先履行切面办法,在来履行本来目标的办法。首要,spring会生成一个目标:UserServiceProxy,这个便是UserService目标的署理目标。咱们用java面向目标思想来考虑,署理目标会承继UserService类,他内部重写了父类的test办法,在里面去履行切面的逻辑,接着经过super.test调用父类办法。这个办法虽然是能够完成,可是在spring中却不是这样的。
【Spring系列】- Bean生命周期底层原理

在Spring中,署理目标里面还会界说一个父类目标UserServicetarget,这个目标最终会赋值这个类生成的目标,也便是bean生命周期最开端遇到的那个目标。Spring经过调用target.test()完成。说白了仍是运用了最本来的那个目标去履行的办法。

【Spring系列】- Bean生命周期底层原理

本文正在参加「金石计划 . 瓜分6万现金大奖」

创作不易,如有错误请纠正,感谢观看!记得点赞哦!