上面是與生命周期有關的內容,下面是屬性賦值相關的:
@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 后置處理器