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 等等

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM