Spring注解(生命周期)

 

对于上面的知识图解,需要一点一点的研究。

 

 首先核心容器:


 

 控制反转 和 依赖注入

    

创建工程:

   maven仓库搜索 spring context  : 

 

 

 引入后

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>

 

以前是通过 application.xml 进行配置设置

配置类 等同于以前的配置文件:

   

package com.toov5.bean;

public class Person {
  int age;
  String name;
  
public Person() {
    
}  
public Person(int age, String name) {
    super();
    this.age = age;
    this.name = name;
}
@Override
public String toString() {
    return "Person [age=" + age + ", name=" + name + "]";
}

}

config:

package com.toov5.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.toov5.bean.Person;

@Configuration
public class config {
   
    @Bean //给容器注册一个Bean,类型为返回值的类型。xml中的id是用方法作为id
    public Person person() {
        return new Person(1, "toov5");
    }
}

测试类:

package com.toov5.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.toov5.bean.Person;
import com.toov5.config.config;

public class test {

    public static void main(String[] args) {

        @SuppressWarnings("resource")
        ApplicationContext applicationContex = new AnnotationConfigApplicationContext(config.class); // 之前是传递配置文件的位置
                                                                                                        // 现在是我们设计的配置类的位置
        Person bean = applicationContex.getBean(Person.class); // 通过类型去获取
        System.out.println(bean);

        String[] beanNamesForType = applicationContex.getBeanNamesForType(Person.class); // 根据类型找到bean的名字
        for (String name : beanNamesForType) {
            System.out.println(name); // 返回bean的名字 我们可以在cofig中配置@Bean的名字
        }

    }

}

 

在xml配置的时候,我们使用的是包扫描的方式

 <context: component-scan base-package= "com.toov5"> </context: conponent-scan>

 包扫描: 只要标注了 @Controller @Service @Repository  @Component

 

用注解搞定:  @ComponentScan(value="com.toov5.bean")

可以指定要扫描的包 

排除的包,包括可以按照 名字 按照类型等去排除   excludeFilters    

指定的包,指定扫描的时候只需要包含哪些组件     includeFilters

还可以通过自定义规则 CUSTOM 通过 implements TypeFilter 重写match方法

   metadataReader : 读取到的当前正在扫描的类的信息

   metadataReaderFactory: 可以获取到其他任何类

 

config:

package com.toov5.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

@Configuration   //标记@Service 和 @Controller的
  @ComponentScan(value="com.toov5",excludeFilters = {
          @Filter(type=FilterType.ANNOTATION,classes= { Controller.class,Service.class })})
//@ComponentScan(value="com.toov5")
public class config {
   
    
}

 controller

package com.toov5.controller;

import org.springframework.stereotype.Controller;

@Controller
public class BookController {
   
}

 

Service

package com.toov5.service;

import org.springframework.stereotype.Service;

@Service
public class BookService {
   
}

 

Dao

package com.toov5.dao;

import org.springframework.stereotype.Repository;

@Repository
public class BookDao {

}

测试:

package com.toov5.test;

import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.toov5.config.config;

public class test {
   
    @SuppressWarnings("resource")
    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(config.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(String name : beanDefinitionNames) {
            System.out.println(name);
        }
    }
    
}

 

 

 config类:

 

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

@Configuration   //标记@Service 和 @Controller的
  @ComponentScan(value="com.toov5",excludeFilters = {
//          @Filter(type=FilterType.ANNOTATION,classes= { Controller.class,Service.class }),
          @Filter(type=FilterType.CUSTOM, classes= {MyTypeFilter.class})
          
         })
//@ComponentScan(value="com.toov5")
public class config {
   
    
}

自定义的:

package com.toov5.config;

import java.io.IOException;

import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;

public class MyTypeFilter implements org.springframework.core.type.filter.TypeFilter{

    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
            throws IOException {
        //获取当前类注解的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前正在扫描的类的类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //获取当前资源(类路径)
         Resource resource = metadataReader.getResource();
         // 获取到类名
         String className = classMetadata.getClassName();
         System.out.println("---->"+className);
         return false;
    }
      
    
}

 运行结果:

 

可以继续往下玩儿:

 

package com.toov5.config;

import java.io.IOException;

import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;

public class MyTypeFilter implements org.springframework.core.type.filter.TypeFilter{

    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
            throws IOException {
        //获取当前类注解的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前正在扫描的类的类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //获取当前资源(类路径)
         Resource resource = metadataReader.getResource();
         // 获取到类名
         String className = classMetadata.getClassName();
         System.out.println("---->"+className);
         //加入校验逻辑
         if (className.contains("er")) {
            return true;   //匹配成功
        }
         return false;
    }
      
}

 

 

@Scope 设置作用域 

    config:

package com.toov5.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.toov5.Bean.Person;

@Configuration   //标记@Service 和 @Controller的
@ComponentScan(value="com.toov5")
public class config {
   
    @Bean
    public Person person() {
        return new Person(12,"toov5");
    }
}

  Test:

package com.toov5.test;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.toov5.config.config;

public class test {
   
    @SuppressWarnings("resource")
    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(config.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(String name : beanDefinitionNames) {
            System.out.println(name);
        }
        //comfig 的@Bean 默认是单例的
        Object p1 = applicationContext.getBean("person");
        Object p2 = applicationContext.getBean("person");
        System.out.println( p1==p2);
    }
    
}

 

prototype: 多实例的

singleton: 单实例的(默认的)

request: 同一次请求创建一个实例

session: 同一个session创建一个实例

 

@Configuration   //标记@Service 和 @Controller的
@ComponentScan(value="com.toov5")
public class config {
   
    @Bean
    @Scope("prototype")
    public Person person() {
        return new Person(12,"toov5");
    }
}

 

 

 单例情况下:

  

public class config {
   
    @Bean(name="people")
    @Scope()
    public Person person() {
        System.out.println("容器创建....");
        return new Person(12,"toov5");
    }
}

测试类启动ioc容器:

 

public class test {
   
    @SuppressWarnings("resource")
    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(config.class);

    }
    
}

单例模式,ioc容器启动后会调用方法创建对象放到IOC容器总  以后每次获取就是直接从容器中获取. 类似于从map获取 map.get()

 

如果是多例模式:

 ioc容器启动是不会创建对象的!

只有调用时候,并且调用一次,获取一次 调用方法创建对象

 config:

@Configuration   //标记@Service 和 @Controller的
@ComponentScan(value="com.toov5")
public class config {
   
    @Bean(name="people")
    @Scope("prototype")
    public Person person() {
        System.out.println("容器创建....");
        return new Person(12,"toov5");
    }
}
public class test {
   
    @SuppressWarnings("resource")
    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(config.class);
        System.out.println("IOC容器创建完成");
        Object p1 = applicationContext.getBean("people");
        System.out.println(p1);
        Object p2 = applicationContext.getBean("people");
        System.out.println(p2);
    }
    
}

 

@Lazy

 懒加载: 单实例bean,默认在容器启动的时候创建对象,懒加载容器启动时候先不创建。第一次在使用获取Bean时候才创建对象,并且进行初始化。

config:

@Configuration   //标记@Service 和 @Controller的
@ComponentScan(value="com.toov5")
public class config {
   
    @Bean(name="people")
    @Lazy
    public Person person() {
        System.out.println("容器创建....");
        return new Person(12,"toov5");
    }
}

测试:

public class test {
   
    @SuppressWarnings("resource")
    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(config.class);
        System.out.println("IOC容器创建完成");
        Object p1 = applicationContext.getBean("people");
        System.out.println(p1);
        Object p2 = applicationContext.getBean("people");
        System.out.println(p2);
    }
    
}

 

 

 第一次获取时候加载。只创建一次。

 

 

 @Condition 按照条件注册bean

    也是springboot 底层大量使用的。 按照一定条件进行判断,满足条件给容器注册Bean

 

 原来情况:

 

@Configuration   //标记@Service 和 @Controller的
@ComponentScan(value="com.toov5")
public class config {
   
    @Bean(name="Jack")
    public Person person1() {
        System.out.println("容器创建....");
        return new Person(50,"马云");
    }
    
    @Bean(name="Linux")
    public Person person2() {
        System.out.println("容器创建....");
        return new Person(51,"Linux");
    }
    
}

测试:

import com.toov5.Bean.Person;
import com.toov5.config.config;

public class test {
   
    @SuppressWarnings("resource")
    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(config.class);
       String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class);
       for(String name : beanNamesForType) {
           System.out.println(name);
       }
    }
    
}

打印:

要求:

如果操作系统是win10 被容器注册 linux

如果是linux  给容器注册 马云

 

 代码:

public class test {
   
    @SuppressWarnings("resource")
    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(config.class);
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        String osName  = environment.getProperty("os.name"); 
        System.out.println(osName);
    
    }
    
}

打印:

 

动态获取环境变量的值

 

context的巧用:

    // 能获取到ioc使用的beanfactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //获取到类加载器
        ClassLoader classLoader = context.getClassLoader();
        //获取到bean定义的注册类 能创建 获取 查询 bean 的定义
        BeanDefinitionRegistry registry = context.getRegistry();

config:

@Configuration   
public class config {
    
    @Conditional({WindowsCondition.class})
    @Bean(name="Windows")
    public Person person1() {
        System.out.println("容器创建....");
        return new Person(50,"Windows");
    }
     
    @Conditional({LinuxCondition.class})
    @Bean(name="Linux")
    public Person person2() {
        System.out.println("容器创建....");
        return new Person(51,"Linux");
    }
    
}

条件:

public class LinuxCondition implements Condition{
  
    // ConditionContext  判断条件能使用的上下文
    // AnnotatedTypeMetadata 注释信息
    
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //判断是否linux 系统    
        //运行时环境信息
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if (property.contains("Linux")) {
            return true;
        }
        return false;
    }

}

条件:

public class WindowsCondition implements Condition {

    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if (property.contains("Windows")) {
            return true;
        }
        return false;
    }
   
}

 

 测试:

 

public class test {
   
    @SuppressWarnings("resource")
    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(config.class);
       String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class);
       for(String name : beanNamesForType) {
           System.out.println(name);
       }
    }
    
}

可以做更多的判断,更多的条件

  

public class WindowsCondition implements Condition {

    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if (property.contains("Windows")) {
            return true;
        }
        
        BeanDefinitionRegistry registry = context.getRegistry();
        boolean result = registry.containsBeanDefinition("Windows"); //容器中是否包含Windows
        // registry 判断没有 可以自己注册一个 非常多的判断条件 也可以给容器中注册bean
        
        
        return false;
    }
   
}

@Condition还可以标注在类上面, 满足当前条件 这个类 中配置的所有Bean注册才能生效

@Configuration  
@Conditional({WindowsCondition.class})
public class config {
        
    @Bean(name="Windows")
    public Person person1() {
        System.out.println("容器创建....");
        return new Person(50,"Windows");
    }
     
    @Bean(name="Linux")
    public Person person2() {
        System.out.println("容器创建....");
        return new Person(51,"Linux");
    }
    
}

打印:

 

 

给容器中注册组件:

 1、 包+组件标注-@Controller @Service  @Repository @Component

 如果导入第三方包呢?

 2、 别人写类: @Bean 导入的第三方包里面的组件

 3、 @Import   快速给容器中导入一个组件  id默认全类名

       @ImportSelector  返回需要导入的组件的全类名数组

 4、Spring提供的FactoryBean

 

测试:

public class test {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(config.class);
   
    private void printBeans(AnnotationConfigApplicationContext applicationContext) {
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(String name : beanDefinitionNames) {
            System.out.println(name);
        }
    }
    
    @Test
    public void test01(){  
        printBeans(applicationContext);
    }
    
}

 

查看Ioc中的bean组件:

 除了ioc自己的,还有那几个正常的

 

 

这么玩儿:

package com.toov5.Bean;

public class Animal {
  String  color ;
  String  name;
  public Animal() {
    // TODO Auto-generated constructor stub
}
public Animal(String color, String name) {
    super();
    this.color = color;
    this.name = name;
}
  
}

config:

public class test {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(config.class);
   
    private void printBeans(AnnotationConfigApplicationContext applicationContext) {
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(String name : beanDefinitionNames) {
            System.out.println(name);
        }
    }
    
    @Test
    public void test01(){  
        printBeans(applicationContext);
    }
    
}

结果:

 

 如果导入多个 ,可以用数组形式@Import({A.class, B.class})

 id 默认是全类名

config:

@Configuration  
@Conditional({WindowsCondition.class})
@Import( {Animal.class , MyImportSelector.class})
public class config {    
    @Bean(name="Windows")
    public Person person1() {
        System.out.println("容器创建....");
        return new Person(50,"Windows");
    }     
    @Bean(name="Linux")
    public Person person2() {
        System.out.println("容器创建....");
        return new Person(51,"Linux");
    }    
}

类:

//自定义逻辑 返回需要导入的组件
public class MyImportSelector  implements ImportSelector{
   //返回值,就是要导入到容器中的组件全类名
  // AnnotationMetadata: 当前标注@Import注解的类的所有注解信息     
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {

        return new String[] {"com.toov5.Bean.Fruit"} ;
    }

}

结果:

 

从容器中获取之:

public class test {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(config.class);
   
    private void printBeans(AnnotationConfigApplicationContext applicationContext) {
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(String name : beanDefinitionNames) {
            System.out.println(name);
        }
    }
    
    @Test
    public void test01(){  
        printBeans(applicationContext);
        Object bean = applicationContext.getBean(Fruit.class);
        System.out.println(bean);
    }
    
}

结果:

 

业务判断:

public class MyImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar{
    //AnnotationMetadata 当前类的注解信息 和 其他信息
    // BeanDefinitionRegistry: BeanDefinition注册类
        //可以调用BeanDefinitionRegistry方法,自定义来注册Bean组件到容器中
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //写逻辑
        Boolean result =registry.containsBeanDefinition("com.toov5.Bean.Fruit"); //容器中是否有电脑
        if (result) { //判断逻辑
            //指定bean的定义信息 包括scope等等
            RootBeanDefinition beanDefinition = new RootBeanDefinition(Pen.class);
            //向容器中注册bean的名字
            registry.registerBeanDefinition("pen", beanDefinition);
        }
    }

}

 

配置:

@Configuration  
@Conditional({WindowsCondition.class})
@Import( {Animal.class , MyImportSelector.class, MyImportBeanDefinitionRegister.class})
public class config {    
    @Bean(name="Windows")
    public Person person1() {
        System.out.println("容器创建....");
        return new Person(50,"Windows");
    }     
    @Bean(name="Linux")
    public Person person2() {
        System.out.println("容器创建....");
        return new Person(51,"Linux");
    }    
}

 

测试:

public class test {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(config.class);
   
    private void printBeans(AnnotationConfigApplicationContext applicationContext) {
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(String name : beanDefinitionNames) {
            System.out.println(name);
        }
    }
    
    @Test
    public void test01(){  
        printBeans(applicationContext);
        Object bean = applicationContext.getBean(Fruit.class);
        System.out.println(bean);
    }
    
}

 

 

FactoryBean 工厂Bean  区别普通的Bean,导入到容器中,容器会调用无参构造器,然后创建一个对象注册到的容器中

工厂Bean 是个工厂, 是个接口

容器调用:

 

返回对象给容器 

 

 还有两个方法:

   

 

创建一个 Pen 的工厂Beran

   

import org.springframework.beans.factory.FactoryBean;

import com.toov5.Bean.Pen;

//创建一个spring 定义的工厂bean
public class PenFactoryBean  implements FactoryBean<Pen>{
    //返回的对象会添加到容器中
    public Pen getObject() throws Exception {
        // TODO Auto-generated method stub
        System.out.println("PenFactoryBean---getBean---");
        return new Pen();
    }

    public Class<?> getObjectType() {
        // TODO Auto-generated method stub
        return Pen.class;
    }
   
    //如果是单例(true) 则在容器中只会保存一份
    public boolean isSingleton() {
        // TODO Auto-generated method stub
        return false;
    }
   //如果是false  则每次获取都会创建新的  即调用 getObject 方法
}

 

然后将工厂bean 加入到容器

@Configuration  
@Import( {Animal.class , MyImportSelector.class, MyImportBeanDefinitionRegister.class})
public class config {    
    
    @Bean
    public PenFactoryBean penFactoryBean() {
        return new PenFactoryBean();
    }
}

 

工厂Bean 获取的是调用getObject创建的对象  

public class test {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(config.class);
   
    private void printBeans(AnnotationConfigApplicationContext applicationContext) {
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(String name : beanDefinitionNames) {
            System.out.println(name);
        }
    }
    
    @Test 
    public void test01(){  
        printBeans(applicationContext);
        Object bean1 = applicationContext.getBean("penFactoryBean");
        Object bean2 = applicationContext.getBean("penFactoryBean");
        System.out.println(bean1==bean2);
        
        Object bean3 = applicationContext.getBean("&penFactoryBean");
        System.out.println(bean3); //加&获取到工厂bean调用getObject创建的对象
                                   //要获取工厂Bean本身,需要id前面加& 否则就是工厂bean的本身了
    }
}

打印:

 

在于其他第三方框架整合时候 FactoryBean用的很多

 

 

方法一: Bean生命周期,Bean创建到初始化,到销毁的过程。由容器管理。

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

xml配置中 通过  init-method  destory-method  配置方法指定

方法二: 注解中:  

   构造(对象创建)

     单例: 在容器启动的时候创建

     多例:在每次获取的时候创建

 

对于生命周期的方法声明,用注解:

  Bean: @Bean(initMethod="init", destroyMethod="destory") 

   

public class Car {
  public Car() {
    System.out.println("无参构造初始化");
}
  public void init() {
    System.out.println("CarBean---init");
} 
  public void destory() {
    System.out.println("CarBean---destory");
  }
}

 config:

@Configuration
public class BeanLife {
   
    @Bean(initMethod="init", destroyMethod="destory") 
    public Car car() {
        return new Car();    
    }
    
}

 

测试方法:

@Test 
    public void test01(){  
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanLife.class);
        System.out.println("容器创建完成");
    }

结果:

关闭容器:

 

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

 

 在数据源的配置过程中 有很多属性的配置需要用到 销毁时候 关闭连接等等

  总结:

    初始化, 对象创建完成,并赋值,调用初始化方法

    销毁, 容器关闭时候。 但是如果是多例情况,创建对象是获取时候才会执行。销毁时候,是不进行的。容器不管的。

 

 方法三: Spring 还提供了两个接口: Bean通过实现InitializingBean (定义初始化逻辑)

                                                                                    DisposableBean (定义销毁逻辑)

 Bean:

@Component
public class Cat implements InitializingBean, DisposableBean{
  
    public Cat() {
        System.out.println("cat 构造函数...");
    }
  //销毁方法
    public void destroy() throws Exception {
        System.out.println("cat destory");
        
    }
  //初始化方法
    public void afterPropertiesSet() throws Exception {
        System.out.println("cat afterPropertiesSet");
        
    }

}

配置:

 

@ComponentScan("com.toov5.Bean")
@Configuration
public class BeanLife {
    
    @Bean(initMethod="init", destroyMethod="destory") 
    public Car car() {
        return new Car();    
    }
    
}

测试:

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

 

 

还可以使用: JSP250规范的   @PostConstruct   在bean创建完成 并且属性赋值完成执行初始化 

                                                  @Predestory  当bean从容器中销毁Bean之前 通知清理工作

 Bean:

@Component
public class Cat implements InitializingBean, DisposableBean{
  
    public Cat() {
        System.out.println("cat 构造函数...");
    }
  //销毁方法
    public void destroy() throws Exception {
        System.out.println("cat destory");
        
    }
  //初始化方法
    public void afterPropertiesSet() throws Exception {
        System.out.println("cat afterPropertiesSet");
        
    }

}

config:

@ComponentScan("com.toov5.Bean")
@Configuration
public class BeanLife {
    
    @Bean(initMethod="init", destroyMethod="destory") 
    public Car car() {
        return new Car();    
    }
    
}

test:

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

 

结果:

 

 还可以使用interface  BeanPostProcessor: 在bean初始化前后进行一些处理工作

     postProcessBeforeInitialization( )   初始化之前工作

     postProcessAfterInitialization( )      初始化之后工作

 

    后置处理器:  初始化前后进行处理工作

     

    

      每个bean在初始化init之前调用 postProcessBeforeInitialization  

                          初始化init 之后调用 postProcessAfterInitialization 

     

   

 对于Bean 的生命周期:

  构造器初始化, 初始化(可以自定义指定),初始化前后可以使用(BeanPostProcessor)进行拦截。 销毁(自定义执行)

 

 

关于BeanPostProcessor 在Spring 底层的使用

     

@Component
public class Dog implements ApplicationContextAware{

    private ApplicationContext applicationContext;
    
   public Dog() {
    System.out.println("dog 构造函数初始化");
  }
   
   @PostConstruct
   public void init() {
       System.out.println("对象创建 并且赋值之后 调用了 @PostConstruct");
   }
   
   @PreDestroy
   public void destory() {
      System.out.println("容器关闭 移除bean,调用了 @PreDestroy");  
   }

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    //dog对象被创建后 ioc容器会被传递进来
    this.applicationContext=applicationContext;    
} 
}

 

BeanValidationPostProcessor

    可以做数据校验, 当对象创建完 给Bean赋值以后。做数据校验

还有

InitDestoryAnnottionBeanPostProcessor

 AutowiredAnnotationBeanPostProcessor    对象创建完了之后 处理所有 @Autowried标注的属性

 

小结: BeanPostProcessor 接口 : bean赋值,注入其他组件,@Autowried,生命周期注解,@Async 等等

 

 

  

 

posted @ 2019-04-04 00:10  toov5  阅读(2054)  评论(0编辑  收藏  举报