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

有不懂的可以参考之前的文章!

https://www.cnblogs.com/Mrchengs/p/10109053.html

 

1.Bean的生命周期

    创建---初始化---销毁
 
容器管理bean的生命周期:
我们可以自定义初始化和销毁的方法
 
构造器: 
    1.单实例:在容器创建好之后创建实例
    2.多实例:在每次获取的时候创建对象
 
初始化:
    对象创建好,并赋值好,进行初始化
销毁:
    单实例:容器关闭的时候
    多实例:容器不会管理这个bean,在容器关闭的时候不会调用销毁的方法

 

1.指定初始化和销毁的方法:通过@Bean的注解
    相当于:init-method,destroy-method
public class Chirld {
     
     public Chirld() {
           System.out.println("创建Child实例....");
     }
     public void init(){
           System.out.println("初始化方法.....");
     }
     public void destroy(){
           System.out.println("销毁方法....");
     }
}
@Configuration
public class TheLifeOfInitAnfDestroy {
     @Bean(initMethod="init",destroyMethod="destroy")
     public Chirld car(){
           return new Chirld();
     }
}
     @Test
     public void test4(){
           AnnotationConfigApplicationContext app = new  AnnotationConfigApplicationContext(TheLifeOfInitAnfDestroy.class);
           
           System.out.println("容器创建完成");
           //关闭
           app.close();
     }
创建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
销毁方法....

 

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

 

 2.接口方法

通过Bean实现InitializingBean自定义初始化逻辑
                       DisposableBean自定义销毁容器
public interface InitializingBean {
     void afterPropertiesSet() throws Exception;
}
public interface DisposableBean {
     void destroy() throws Exception;
}

 

 

@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....");
     }
}
@Configuration
@ComponentScan("coom.MrChengs.bean")
public class TheLifeOfInitAnfDestroy {

}
@Test
     public void test4(){
           AnnotationConfigApplicationContext app = new  AnnotationConfigApplicationContext(TheLifeOfInitAnfDestroy.class);
           
           System.out.println("容器创建完成");
           //关闭
           app.close();
     }

 

 

创建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....

 

 

3.可以使用JSR250
    @PostConStruct:在bean创建完成并且属性赋值完成,来执行初始化
    @PreDestroy:在容器销毁bean之前通知我们进行清理

 

//代码.....

 

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

在bean初始化之后进行一些处理工作
  postProcessBeforeInitialization:在初始化之前工作
 
  postProcessAfterInitialization:  在初始化之后工作
@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;
     }
}
@Configuration
@ComponentScan("coom.MrChengs.bean")
public class TheLifeOfInitAnfDestroy {
}
     @Test
     public void test4(){
           AnnotationConfigApplicationContext app = new  AnnotationConfigApplicationContext(TheLifeOfInitAnfDestroy.class);
           System.out.println("容器创建完成");
           //关闭
           app.close();
     }

 

 

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

person.school=MrChengs
public class Person {
     
     @Value("MrChengs")
     private String name;
     @Value("#{20-12}")
     private int age;
     @Value("${person.school}")
     private String school;
...
}

 

@Configuration
//引入资源 @PropertySource(value
={"classpath:/person.properties"}) public class ValueConfig { @Bean public Person person(){ return new Person(); } }

 

@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"})用于加载配置文件
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去容器中查找
applicationContext.getBean("customerDao")...

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

 

3.  @Qualifier
指定需要装配的组件id
 @Qualifier("customerDao")
     @Autowired
     private CustomerDao customerDao2;
4.默认一定将属性赋值好
5.如果没有的情况下组件默认是null
    不是必须的,此时容器中没有所需要装配的bean也不会报错
     @Qualifier("customerDao")
     @Autowired(required=false)
     private CustomerDao customerDao2;

 

6.@Primary:让spring进行装配的时候,默认使用首选的bean

     @Autowired(required=false)
     private CustomerDao customerDao;


     @Primary
     @Bean("customerDao2")
     public CustomerDao customer(){
    ...
}

 

@Repository
public class CustomerDao {
}
@Service
public class CustomerService {
     @Autowired
     private CustomerDao customerDao;
     
     public void print(){
           System.out.println("---->"+customerDao);
     }
}

 

@Configuration
@ComponentScan({"coom.MrChengs.config.service","coom.MrChengs.config.dao"})
public class AutowiredConfig {
     @Bean("customerDao2")
     public CustomerDao customer(){
           return new CustomerDao("customer2");
     }
     
}

 

     @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); }

 

autowiredConfig
customerService

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

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

 

 

spring还支持@Resource@Inject   java规范注解
@Resource
可以实现和@Autowire一样的功能 实现,默认是按照组件的名称进行装配
     @Resource
     private CustomerDao customerDao;

 

 

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

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

 

 

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

 

@Inject
需要导入下面的依赖
<!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>
     @Inject
     private CustomerDao customerDao;
其实先功能和@Autowire功能一样
其本身没有属性,没有require=false这个属性
支持@Primary

 

@Autowire

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD,  
ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented
public @interface Autowired {

 

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

 

方法上

@Component
public class Person {
...
}
@Component
public class Students {
...
     @Autowired
     public void setPerson(Person person) {
           this.person = person;
     }
..
}
     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}]

 

 

构造器:
     @Autowired
     public Students(Person person, String name) {
           super();
           this.person = person;
           this.name = name;
           System.out.println("Students.....");
     }
1.标注在方法位置上,@Bean+方法参数,参数从容器中获取
2.标注在构造器上:如果组件只有一个构造函数,可以省略
3.放在参数位置

 

posted @ 2018-12-12 17:37  MrChengs  阅读(320)  评论(0编辑  收藏  举报