Spring注解(賦值相關)


上面是與生命周期有關的內容,下面是屬性賦值相關的:

@Configuration
public class ProperTyValueConfig {
    
    @Bean
    public Person person() {
        return new Person();
    }
}

測試:

public class test {
    
    private void printBeans(AnnotationConfigApplicationContext applicationContext) {
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(String name : beanDefinitionNames) {
            System.out.println(name);
        }
        Object p = applicationContext.getBean("person");
        System.out.println(p);
    }
    
    @Test 
    public void test01(){  
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ProperTyValueConfig.class);
        System.out.println("容器創建完成");
        printBeans(applicationContext);
        //關閉容器
        applicationContext.close();
    }
    
} 

 

看看容器有哪些Bean

除了容器自帶的,還有就是我們配置的person,還沒有賦值哦

 

 xml:

 <baen  id = "person"  class = "com.toov5.Person"> 

   <property name = "age" value= 12> </property>

  <property name="name" value = "jack"> </property>

</bean>

 注解:

  @Value()   boolean 

  Spel  基本數值都可以寫 #{}

  ${} 取出配置文件中的值  在運行環境中的變量值

 

Bean類及其賦值:

 

package com.toov5.Bean;

import org.springframework.beans.factory.annotation.Value;

public class Person {
  
 @Value("#{20-1}")
  int age;

 @Value("MaYun")
  String name;
 
public Person() {
    // TODO Auto-generated constructor stub
}

public Person(int age, String name) {
    super();
    this.age = age;
    this.name = name;
}

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

注意賦值 @Value 類型要匹配

 

下面介紹使用properties文件的:

   如果用xml形式的讀取:

   xml中需要有命名空間:  <context: property-placeholder location=“xxxxxx/xxx” />    用其導入外部的配置文件

  

  如果用注解的方式讀取:

config:

@Configuration
@PropertySource(value= {"classpath"/person.properties"})
public class ProperTyValueConfig {
    
     @Bean
        public Person person() {
            return new Person();
        }
}

 

   Bean類:

   

public class Person {
  
 @Value("#{20-1}")
  int age;

 @Value("MaYun")
  String name;
 
 @Value("${person.addr}")
  String addr;
 
public Person() {
    // TODO Auto-generated constructor stub
}

public Person(int age, String name) {
    super();
    this.age = age;
    this.name = name;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getAddr() {
    return addr;
}

public void setAddr(String addr) {
    this.addr = addr;
}

@Override
public String toString() {
    return "Person [age=" + age + ", name=" + name + ", addr=" + addr + "]";
}
  
}

 

properties:

  

  person.addr=beijing

 

 測試:

  

public class test {
    
    private void printBeans(AnnotationConfigApplicationContext applicationContext) {
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(String name : beanDefinitionNames) {
            System.out.println(name);
        }
        Object p = applicationContext.getBean("person");
        System.out.println(p);
    }
    
    @Test 
    public void test01(){  
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ProperTyValueConfig.class);
        System.out.println("容器創建完成");
        printBeans(applicationContext);
        //關閉容器
        applicationContext.close();
    }
    
} 

 

 一旦properties文件被加載,還可以使用如下方式獲取:

  

public class test {
    
    private void printBeans(AnnotationConfigApplicationContext applicationContext) {
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(String name : beanDefinitionNames) {
            System.out.println(name);
        }
        Object p = applicationContext.getBean("person");
        System.out.println(p);
        //運行時環境變量
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        String property = environment.getProperty("person.addr");
        System.out.println(property);
        
    }
    
    @Test 
    public void test01(){  
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ProperTyValueConfig.class);
        System.out.println("容器創建完成");
        printBeans(applicationContext);
        //關閉容器
        applicationContext.close();
    }
    
} 

 

  

自動裝配:

 Spring 利用依賴注入(DI),完成IOC容器中格個組件的依賴關系賦值

 

Service

@Service
public class BookService {
    
    @Autowired
    private BookDao bookDao;
    
    public void print() {
        System.out.println(bookDao);
    }
    @Override
    public String toString() {
        return "BookService"+bookDao;
    }
}

config:

@Configuration
@ComponentScan({"com.toov5.dao","com.toov5.service","com.toov5.controller"})
public class ProperTyValueConfig {
    
}

test:

public class test {

    @Test 
    public void test01(){  
        AnnotationConfigApplicationContext applicationContext  =new AnnotationConfigApplicationContext(ProperTyValueConfig.class);
        BookService bookService =(BookService) applicationContext.getBean(BookService.class); //按照類型去拿
        System.out.println(bookService);
        applicationContext.close();
    }
    
} 

 

 有了dao哦

其實就是容器中的到哦:

 

 @Autowired 自動注入

  默認優先按照類型去容器找對應的組件:  applicationContext.getBean(BookService.class);

  找到則賦值

  如果這個類型的組件在IOC中有多個,怎么處理?

   容器中有兩個類型相同 名字不同的bean

   如果找到多個相同類型的組件,再將屬性名作為組件的id 去容器中查找。applicationContext.getBean("bookDao") 

 

 在裝配時候:

  名字是bookDao2

@Service
public class BookService {
    
    @Autowired
    private BookDao bookDao2;
    
    public void print() {
        System.out.println(bookDao2);
    }
    @Override
    public String toString() {
        return "BookService"+bookDao2.getFlag();
    }
}

config注入的是 bookDao2

@Configuration
@ComponentScan({"com.toov5.dao","com.toov5.service","com.toov5.controller"})
public class ProperTyValueConfig {
    
    @Bean(name="bookDao2")
    public BookDao bookDao() {
         BookDao bookDao = new BookDao();
         bookDao.setFlag("2");
         return bookDao;
    }
}

 

 測試:

public class test {

    @Test 
    public void test01(){  
        AnnotationConfigApplicationContext applicationContext  =new AnnotationConfigApplicationContext(ProperTyValueConfig.class);
        BookService bookService =(BookService) applicationContext.getBean(BookService.class); //按照類型去拿
        System.out.println(bookService);
        
        BookDao bookDao = applicationContext.getBean(BookDao.class);
        System.out.println(bookDao.getFlag());
        
        applicationContext.close();
    }  
} 

 

可以在裝配時候這么玩兒

  @Qualifier("bookDao")   指定需要抓給你配的組件的id 而不是屬性名

@Service
public class BookService {
    
    @Qualifier("bookDao")
    @Autowired
    private BookDao bookDao2;
    
    public void print() {
        System.out.println(bookDao2);
    }
    @Override
    public String toString() {
        return "BookService"+bookDao2.getFlag();
    }
}

打印:

自動裝配默認一定要將屬性賦值好,沒有就會報錯

如果:

@Service
public class BookService {
    
    @Qualifier("bookDao")
    @Autowired(required=false)
    private BookDao bookDao2;
    
    public void print() {
        System.out.println(bookDao2);
    }
    @Override
    public String toString() {
        return "BookService"+bookDao2.getFlag();
    }
}

如果沒有的情況下,不報錯:

@Service
public class BookService {
    
    @Qualifier("bookDao666")
    @Autowired(required=false)
    private BookDao bookDao2;
    
    public void print() {
        System.out.println(bookDao2);
    }
}

測試:

public class test {

    @Test 
    public void test01(){  
        AnnotationConfigApplicationContext applicationContext  =new AnnotationConfigApplicationContext(ProperTyValueConfig.class);
        BookService bookService =(BookService) applicationContext.getBean(BookService.class); //按照類型去拿
        bookService.print();
    
        applicationContext.close();
    }  
} 

打印:

 

容器中沒有的情況 會null

 

還有一個spring的牛逼的注解 @Primary  讓spring自動裝配的時候 默認使用首選bean

@Configuration
@ComponentScan({"com.toov5.dao","com.toov5.service","com.toov5.controller"})
public class ProperTyValueConfig {
    
    @Primary
    @Bean(name="bookDao2")
    public BookDao bookDao() {
         BookDao bookDao = new BookDao();
         bookDao.setFlag("2");
         return bookDao;
    }
}

每次首選裝配的是加了 @Primary的

既然已經在容器中聲明了 在裝配時候 @Qualifier 就不需要了

使用首選來裝配

如果加了@Qualifier 那就是明確指定的了

service:

@Service
public class BookService {
    
    @Autowired(required=false)
    private BookDao bookDao;
    
    public void print() {
        System.out.println(bookDao.getFlag());
    }
}

config 明確了優先裝配的bean

@Configuration
@ComponentScan({"com.toov5.dao","com.toov5.service","com.toov5.controller"})
public class ProperTyValueConfig {
    
    @Primary
    @Bean(name="bookDao2")
    public BookDao bookDao() {
         BookDao bookDao = new BookDao();
         bookDao.setFlag("2");
         return bookDao;
    }
}

測試:

public class test {

    @Test 
    public void test01(){  
        AnnotationConfigApplicationContext applicationContext  =new AnnotationConfigApplicationContext(ProperTyValueConfig.class);
        BookService bookService =(BookService) applicationContext.getBean(BookService.class); //按照類型去拿
        bookService.print();
    
        applicationContext.close();
    }  
} 

 Spring還支持使用 @Resource(JSR250) java 規范的注釋   @Qualifier+ @Autowired = @Resource 或者 @Resource(name="bookDao2") 否則就默認當前的屬性名字

                         和 @Inject(JSP330)  需要額外導入依賴 (maven倉庫搜索inject)  Autowried可以設置required屬性

 

 

@Autowried構造器  參數 方法 屬性 都可以標注使用

 CarBean:

@Component
public class Car {
  public Car() {
    System.out.println("無參構造初始化");
}
  public void init() {
    System.out.println("CarBean---init");
} 
  public void destory() {
    System.out.println("CarBean---destory");
  }
}

BossBean:  默認加載IOC容器中的組件,容器會調用無參構造器創建對象,在進行初始化賦值等操作。

@Component
public class Boss {

    private Car car;
    
    public Car getCar() {
        return car;
    }
    @Autowired //標注在方法上 spring容器創建對象時候 調用方法 完成賦值。方法使用的參數,自定義類型的值 從IOC獲取值
    public void setCar(Car car) {
        this.car = car;
    }
}

 

config:

@Configuration
@ComponentScan({"com.toov5.Bean"})
public class ProperTyValueConfig {
    
    @Primary
    @Bean(name="bookDao2")
    public BookDao bookDao() {
         BookDao bookDao = new BookDao();
         bookDao.setFlag("2");
         return bookDao;
    }
}

測試:

public class test {
    @Test 
    public void test01(){  
        AnnotationConfigApplicationContext applicationContext  =new AnnotationConfigApplicationContext(ProperTyValueConfig.class);
        Boss boss =(Boss) applicationContext.getBean(Boss.class); //按照類型去拿
        System.out.println(boss.getCar());
      //再從容器中獲取car  進行比對
        Car carBean =applicationContext.getBean(Car.class);
        System.out.println(carBean);
        applicationContext.close();
    }  
} 

打印:

來個有參構造器: 標注在有參構造器上面: Spring啟動時候 調用有參構造器

@Component
public class Boss {

    private Car car;
    
    @Autowired 
    public Boss(Car car) {
        this.car=car;
        System.out.println("Boss 有參構造器  ");
    }
    
    public Car getCar() {
        return car;
    }
 //    @Autowired //標注在方法上 spring容器創建對象時候 調用方法 完成賦值。方法使用的參數,自定義類型的值 從IOC獲取值
    public void setCar(Car car) {
        this.car = car;
    }
}

 

 當然也可以放在參數位置:

    public Boss(@Autowired  Car car) {
        this.car=car;
        System.out.println("Boss 有參構造器  ");
    }

如果只有一個有參構造器,注解可以省略。建議平時大家開發時候還是不要省略了吧

 

也可以在config里面這么玩兒

@Configuration
@ComponentScan({"com.toov5.Bean"})
public class ProperTyValueConfig {
    
    @Primary
    @Bean(name="boss")
    public Boss boss(Car car) {
        Boss boss =new Boss();
        boss.setCar(car);
        return boss;
        
    }
}

Bean標注的方法創建對象的時候,方法參數的值從容器中獲取!

原理可以看Aware接口

 可以看下這個:

 

 

 

 

 啟動容器后,創建對象,需要的其他組件都會以接口方法回調的方式引入進來

 bean:

 

@Component
public class Animal implements ApplicationContextAware,BeanNameAware,EmbeddedValueResolverAware {
  private ApplicationContext applicationContext;    
  String  color ;
  String  name;
  public Animal() {
    // TODO Auto-generated constructor stub
}
public Animal(String color, String name) {
    super();
    this.color = color;
    this.name = name;
}
//第一個接口
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    System.out.println("傳入IOC:"+applicationContext);
    this.applicationContext=applicationContext;
    
}
//第二個接口
public void setBeanName(String name) {  //傳入bean名字 通過名字去容器查找bean
    System.out.println("當前bean的名字"+name);
    
}
//第三個接口 
//容器啟動時候  創建對象 然后把resolver對象傳遞進來  
public void setEmbeddedValueResolver(StringValueResolver resolver) { //解析字符串 # {}  等等
    // TODO Auto-generated method stub
    String resolveStringValue = resolver.resolveStringValue("你好${os.name} 我是#{30*1}");
    System.out.println("解析的字符串"+resolveStringValue);
}

}

config:

@Configuration
@ComponentScan({"com.toov5.Bean"})
public class ProperTyValueConfig {
    
    @Primary
    @Bean(name="boss")
    public Boss boss(Car car) {
        Boss boss =new Boss();
        boss.setCar(car);
        return boss;  
    }
}

測試:

public class test {
    @Test 
    public void test01(){  
        AnnotationConfigApplicationContext applicationContext  =new AnnotationConfigApplicationContext(ProperTyValueConfig.class);
        Boss boss =(Boss) applicationContext.getBean(Boss.class); //按照類型去拿
        System.out.println(boss.getCar());
      //再從容器中獲取car  進行比對
        Car carBean =applicationContext.getBean(Car.class);
        System.out.println(carBean);
        applicationContext.close();
    }  
} 

 

 打印:

 自定義組件想要使用Spring容器底層的一些組件 (ApplicationContext  BeanFactory...) 

 自定義組件實現xxxAware; 在創建對象的時候,會調用接口規定的方法注入相關組件; Aware; 把Spring  底層一些組件注入到自定義的Bean

 

 每個xxxAware 都會有相關的  xxxAwareProcessor   后置處理器

 


免責聲明!

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



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