Fork me on GitHub

Spring:生命周期,属性赋值,自动装配

1.Bean的生命周期

创建—初始化—销毁

容器管理bean的生命周期:

我们可以自定义初始化和销毁的方法

构造器:

1.单实例:在容器创建好之后创建实例

2.多实例:在每次获取的时候创建对象

初始化:

对象创建好,并赋值好,进行初始化

销毁:

单实例:容器关闭的时候

多实例:容器不会管理这个bean,在容器关闭的时候不会调用销毁的方法

  1. 指定初始化和销毁的方法:通过@Bean的注解

    相当于:init-method,destroy-method

1
2
3
4
5
6
7
8
9
10
11
12
public class Chirld {

public Chirld() {
System.out.println("创建Child实例....");
}
public void init(){
System.out.println("初始化方法.....");
}
public void destroy(){
System.out.println("销毁方法....");
}
}
1
2
3
4
5
6
7
@Configuration
public class TheLifeOfInitAnfDestroy {
@Bean(initMethod="init",destroyMethod="destroy")
public Chirld car(){
return new Chirld();
}
}
1
2
3
4
5
6
7
8
@Test
public void test4(){
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(TheLifeOfInitAnfDestroy.class);

System.out.println("容器创建完成");
//关闭
app.close();
}
1
2
3
4
5
6
创建Child实例....
初始化方法.....
容器创建完成
十一月 16, 2018 12:19:32 上午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@512ddf17: startup date [Fri Nov 16 00:19:32 CST 2018]; root of context hierarchy
销毁方法....

在容器关闭的时候进行销毁

  1. 接口方法

通过Bean实现InitializingBean自定义初始化逻辑

​ DisposableBean自定义销毁容器

1
2
3
4
5
6
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
public interface DisposableBean {
void destroy() throws Exception;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Component
public class Chirld2 implements InitializingBean,DisposableBean {

public Chirld2() {
System.out.println("创建Child2实例....");
}
public void afterPropertiesSet() throws Exception {
System.out.println("init.....");

}
public void destroy() throws Exception {
System.out.println("destroy....");
}
}
1
2
3
4
5
@Configuration
@ComponentScan("coom.MrChengs.bean")
public class TheLifeOfInitAnfDestroy {

}
1
2
3
4
5
6
7
8
@Test
public void test4(){
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(TheLifeOfInitAnfDestroy.class);

System.out.println("容器创建完成");
//关闭
app.close();
}
1
2
3
4
5
6
创建Child2实例....
init.....
容器创建完成
十一月 16, 2018 12:35:43 上午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@512ddf17:   startup date [Fri Nov 16 00:35:43 CST 2018]; root of context hierarchy
destroy....
  1. 可以使用JSR250

    @PostConStruct:在bean创建完成并且属性赋值完成,来执行初始化

    @PreDestroy:在容器销毁bean之前通知我们进行清理

//代码…..

4.BeanPostProcessor接口:bean的后置处理器

在bean初始化之后进行一些处理工作

  postProcessBeforeInitialization:在初始化之前工作

  postProcessAfterInitialization: 在初始化之后工作

1
2
3
4
5
6
7
8
9
10
11
12
13
@Component
public class MyBeanPostProcessor implements BeanPostProcessor{
//bean:刚刚创建的实例
//beanName:bean的名字
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("post init.....");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("aftet init ....");
return bean;
}
}
1
2
3
4
@Configuration
@ComponentScan("coom.MrChengs.bean")
public class TheLifeOfInitAnfDestroy {
}
1
2
3
4
5
6
7
@Test
public void test4(){
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(TheLifeOfInitAnfDestroy.class);
System.out.println("容器创建完成");
//关闭
app.close();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
post init.....
aftet init ....
post init.....
aftet init ....
post init.....
aftet init ....
创建Child2实例....
post init.....
init.....
aftet init ....
容器创建完成
十一月 16, 2018 8:25:25 上午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@512ddf17: startup date [Fri Nov 16 08:25:24 CST 2018]; root of context hierarchy
destroy....

底层对BeanPostProcessor的使用:

bean赋值,注入其他组建,@Autowire,生命周期注解功能。。。。。

2.属性赋值:

@Value(“”)

1.基本数值

2.可以写Spel : #{}

3.可以写 ${ } ,取出配置文件中的只

person.properties

1
person.school=MrChengs
1
2
3
4
5
6
7
8
9
10
public class Person {

@Value("MrChengs")
private String name;
@Value("#{20-12}")
private int age;
@Value("${person.school}")
private String school;
...
}
1
2
3
4
5
6
7
8
@Configuration//引入资源
@PropertySource(value={"classpath:/person.properties"})
public class ValueConfig {
@Bean
public Person person(){
return new Person();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void test5(){
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(ValueConfig.class);

String [] names = app.getBeanDefinitionNames();
for(String name : names){
System.out.println(name);
}
Person person = app.getBean(Person.class);
System.out.println(person);

}

valueConfig
person
Person [name=MrChengs, age=8, school=MrChengs]

@PropertySource(value={“classpath:/person.properties”})用于加载配置文件

1
2
3
4
5
6
7
8
9
10
11
12
public @interface PropertySource {

String name() default "";

String[] value();

boolean ignoreResourceNotFound() default false;

String encoding() default "";

Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}

自动装配:

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

前提自动注入的需要提前在容器中

@Autowired

  1. 默认优先按照类型进行容器组件中查找

  2. 当容器中有多个相同类型的组件,再将属性的名作为组件的id去容器中查找

1
2
3
4
5
applicationContext.getBean("customerDao")...

@Autowired
private CustomerDao customerDao;
默认按照方法名去id中查找
  1. @Qualifier

指定需要装配的组件id

1
2
3
@Qualifier("customerDao")
@Autowired
private CustomerDao customerDao2;
  1. 默认一定将属性赋值好

  2. 如果没有的情况下组件默认是null

    不是必须的,此时容器中没有所需要装配的bean也不会报错

1
2
3
@Qualifier("customerDao")
@Autowired(required=false)
private CustomerDao customerDao2;
  1. @Primary:让spring进行装配的时候,默认使用首选的bean
1
2
3
4
5
6
7
8
9
     @Autowired(required=false)
private CustomerDao customerDao;


@Primary
@Bean("customerDao2")
public CustomerDao customer(){
...
}
1
2
3
@Repository
public class CustomerDao {
}
1
2
3
4
5
6
7
8
9
@Service
public class CustomerService {
@Autowired
private CustomerDao customerDao;

public void print(){
System.out.println("---->"+customerDao);
}
}
1
2
3
4
5
6
7
8
9
@Configuration
@ComponentScan({"coom.MrChengs.config.service","coom.MrChengs.config.dao"})
public class AutowiredConfig {
@Bean("customerDao2")
public CustomerDao customer(){
return new CustomerDao("customer2");
}

}
1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void test6(){
AnnotationConfigApplicationContext app = new     AnnotationConfigApplicationContext(coom.MrChengs.config.AutowiredConfig.class);

String [] names = app.getBeanDefinitionNames();
for(String name : names){
System.out.println(name);
}
CustomerService cus = app.getBean(CustomerService.class);
cus.print();
//System.out.println(cus);
}
1
2
3
4
5
6
7
8
9
autowiredConfig
customerService

此时容器中有两个相同类型的bean
customerDao
customerDao2

此时注入的类型是:
---->CustomerDao [name=null]

spring还支持@Resource和@Inject java规范注解

@Resource

可以实现和@Autowire一样的功能 实现,默认是按照组件的名称进行装配

1
2
@Resource
private CustomerDao customerDao;

可以修改器默认装配的名称

1
2
@Resource(name="customerDao2")
private CustomerDao customerDao;

不可以支持@Primary功能和request=false的功能

@Inject

需要导入下面的依赖

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
1
2
@Inject
private CustomerDao customerDao;

其实先功能和@Autowire功能一样

其本身没有属性,没有require=false这个属性

支持@Primary

@Autowire

1
2
3
4
5
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD,  ElementType.PARAMETER, ElementType.FIELD,  ElementType.ANNOTATION_TYPE})

@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

可以标注的位置有构造器,方法,属性

方法上

1
2
3
4
@Component
public class Person {
...
}
1
2
3
4
5
6
7
8
9
@Component
public class Students {
...
@Autowired
public void setPerson(Person person) {
this.person = person;
}
..
}
1
2
3
4
5
6
7
AnnotationConfigApplicationContext app = new  AnnotationConfigApplicationContext(coom.MrChengs.config.AutowiredConfig.class);

Students s = app.getBean(Students.class);

System.out.println(s);
Person p = app.getBean(Person.class);
System.out.println(p);

Students [person=Person [name=MrChengs, age=8, school=${person.school}], name=null]
Person [name=MrChengs, age=8, school=${person.school}]

构造器:

1
2
3
4
5
6
7
@Autowired
public Students(Person person, String name) {
super();
this.person = person;
this.name = name;
System.out.println("Students.....");
}

1.标注在方法位置上,@Bean+方法参数,参数从容器中获取

2.标注在构造器上:如果组件只有一个构造函数,可以省略

3.放在参数位置

原文链接

相关文章

评论系统未开启,无法评论!