java成员属性生命周期,Spring注解 - 生命周期、属性赋值、自动装配

一、Bean的生命周期

流程

Bean创建 —— 初始化 —— 销毁

创建:

单实例:在容器启动时创建对象

多实例:每次调用时创建对象

初始化:

都是在对象创建完成后,调用初始化方法

销毁:

单实例:容器关闭时,调用销毁方法

多实例:容器不会管理这个bean,只能手动调用销毁方法

实现方式

在 @Bean 注解上指定初始化(initMethod)、销毁方法(destroyMethod) @Bean(initMethod = "init", destroyMethod = "destroy")

public Car car(){

return new Car();

}

让Bean实现 InitializingBean 和 DisposableBean 接口,重写它们的方法 public class Cat implements InitializingBean, DisposableBean {

public Cat() {

System.out.println("Cat...Construct...");

}

@Override

public void afterPropertiesSet() throws Exception {

System.out.println("Cat...init...");

}

@Override

public void destroy() throws Exception {

System.out.println("Cat...destroy...");

}

}

使用 JSR250 中的 @PostConstruct 和 @PreDestroy 注解标注初始化、销毁方法 public class Dog {

public Dog() {

System.out.println("Dog...Construct...");

}

@PostConstruct

public void init(){

System.out.println("Dog...init...");

}

@PreDestroy

public void destroy(){

System.out.println("Dog...destroy...");

}

}

实现BeanPostProcessor接口,重写

postProcessBeforeInitialization(在初始化之前工作)

postProcessAfterInitialization(在初始化之后工作) public class MyBeanPostProcessor implements BeanPostProcessor {

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

System.out.println("postProcessBeforeInitialization" + beanName);

return bean;

}

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

System.out.println("postProcessAfterInitialization" + beanName);

return bean;

}

}

二、属性赋值相关注解

作用:

​ 添加在字段上,用于给属性赋值

属性:

value:指定要传入的值

用法:

public class Person {

@Value("张三") //普通方式赋值

private String name;

@Value("#{20 - 1}") //使用SpEL表达式

private Integer age;

@Value("${person.nickName}") //使用 ${} 读取配置文件内容

private String nickName;

//省略getter setter toString方法

}

上述第三种方式显然是不能读取到的,我们需要配置一下配置文件的位置,使用到下面这个注解

@PropertySource

作用:

​ 读取指定的外部配置文件,将K/V键值对保存到运行的环境变量中,用 ${} 来获取

属性:

name:给属性源指定一个名称

value:要加载的配置文件的路径,可以指定多个

ignoreResourceNotFound:是否忽略资源未找到的情况,默认false

encoding:给定资源的特定字符编码,例如 “UTF-8”

factory:指定一个自定义属性源工厂,默认使用 PropertySourceFactory

用法:

在 resources 目录下创建一个 properties 文件,内容如下

person.nickName=小张

然后在配置类上标注 @PropertySource("classpath:person.properties") 即可

可以直接在@Value注解中获取,也可以通过 ioc 容器对象获取

ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfiguration4.class);

String nickName = context.getEnvironment().getProperty("person.nickName");

System.out.println(nickName);

三、自动装配相关注解

Spring 利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值

@Autowired

默认按照类型去容器中寻找对应的组件,如果只有一个就赋值

如果找到多个相同类型的组件,再按照属性名寻找

有一个required属性,默认是true;

可以写在构造器、方法、参数、属性上

@Qualifier

一般配合 @Autowired 使用,指定需要装配的组件的id,@Autowired 就直接按照id注入。

如果 id 对应的组件不存在,并且没有指定 required = false,则会报错

@Primary

让Spring进行自动装配的时候,首先选择标注了@Primary的组件

如果已经使用 @Qualifier 指明了要装配的组件,则不生效

👇 不常用的两个自动注入注解:

@Resource(JSR250)

java规范里的注解,和@Autowired一样可以实现自动装配

默认使用变量名作为 id,不能配合@Qualifier @Primary使用

@Inject(JSR330)

和@Autowired一样,但是没有required属性,需要导入 javax.inject 的 jar 包

javax.inject

javax.inject

1

@Profile

指定组件在哪个环境下才被注册到容器中,不指定则在哪个环境都注册

可以指定多个环境,default为默认环境

可以写在配置类上

还可以用代码的方式指定环境

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration5.class);

applicationContext.getEnvironment().setActiveProfiles("prod");

四、使用 Spring 容器底层组件

对于自定义组件,如果想要使用Spring容器底层组件,可以实现Aware接口的子接口(xxxAware),如下图所示

cb9f9a343fc1d3f1aa6a0538d6125bd5.png

@Component

public class TestAware implements ApplicationContextAware {

private ApplicationContext applicationContext;

@Override

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

System.out.println("传入的IOC容器:" + applicationContext);

this.applicationContext = applicationContext;

}

}

这些 xxxAware 的功能都是通过 ApplicationContextAwareProcessor 来处理的

class ApplicationContextAwareProcessor implements BeanPostProcessor {

private final ConfigurableApplicationContext applicationContext;

private final StringValueResolver embeddedValueResolver;

/**

* Create a new ApplicationContextAwareProcessor for the given context.

*/

public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {

this.applicationContext = applicationContext;

this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());

}

@Override

@Nullable

public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {

AccessControlContext acc = null;

if (System.getSecurityManager() != null &&

(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||

bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||

bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {

acc = this.applicationContext.getBeanFactory().getAccessControlContext();

}

if (acc != null) {

AccessController.doPrivileged((PrivilegedAction) () -> {

invokeAwareInterfaces(bean);

return null;

}, acc);

}

else {

invokeAwareInterfaces(bean);

}

return bean;

}

//根据传入bean的类型来为bean注入不同的组件

private void invokeAwareInterfaces(Object bean) {

if (bean instanceof Aware) {

if (bean instanceof EnvironmentAware) {

((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());

}

if (bean instanceof EmbeddedValueResolverAware) {

((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);

}

if (bean instanceof ResourceLoaderAware) {

((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);

}

if (bean instanceof ApplicationEventPublisherAware) {

((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);

}

if (bean instanceof MessageSourceAware) {

((MessageSourceAware) bean).setMessageSource(this.applicationContext);

}

if (bean instanceof ApplicationContextAware) {

((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);

}

}

}

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) {

return bean;

}

}

```

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值