spring ioc其實就是控制翻轉,幫你創建對象,不用在自己創建。在需要聚合引入時也會處理對象之間的關係。
ioc其實就是分兩步:
第一步:將自己的對象寫好後加上能被spring掃描的註解,通常的註解有:@Configuration,@Component,@Service,@Controller等等,看似好多被掃描標識的註解,其實具有被掃描功能的只有@Component,其他註解內部只是包含@Component所有才有了被掃描的功能,因爲不會有人喜歡寫重複冗餘的代碼,尤其是工具,所以spring也不會例外。
第二步:掃描的註解是:@ComponentScan,通過指定或默認掃描的範圍去掃描標識過的對象,然後創建並加載到ico容器中,可通過ico容器的getBean方法將指定的對象取出使用。
1.ioc容器:org.springframework.context.ApplicationContext,這只是個接口,下面有很多的實現類,也就是說有很多的ico實現容器。我們這裏使用的是其中一個叫import org.springframework.context.annotation.AnnotationConfigApplicationContext;的容器做demo演示。
2.掃描註解:@ComponentScan(basePackages = {"com.mr.li.*" }/* , excludeFilters = {@Filter(classes = {Person.class, Animal.class})} */) :掃描註解見名知意就是用來掃描需要加載到ico容器中的java類的。可以指明掃描範圍,例如填寫包名,也可過濾哪些不被掃描 excludeFilters中的內容就是不被掃描的。掃描的註解也較多如:@ComponentScans,@EntityScan,@EnableAsync
上代碼:
1:先指定掃描哪些包,包括在裏面也創建一些被ioc加載的bean
package com.mr.li.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import com.mr.li.entity.User; @Configuration @ComponentScan(basePackages = { "com.mr.li.*" }/* , excludeFilters = {@Filter(classes = {Person.class, Animal.class})} */) public class AppConfig { @Bean(value = "user1") public User getUser() { User user = new User(); user.setId(1000); user.setName("旺達"); return user; } @Bean(value = "user2") public User getUser2() { User user = new User(); user.setId(1001); user.setName("天天"); return user; } }
2.創建一些服務接口
package com.mr.li.service; public interface Person { void behavior(); }
package com.mr.li.service; public interface Animal { void behavior(); }
3,給這些接口一些實現類
package com.mr.li.service.impl; import org.springframework.stereotype.Component; import com.mr.li.service.Animal; @Component public class Cat implements Animal { @Override public void behavior() { System.out.println("喵喵喵~~~~~~~~~"); } }
package com.mr.li.service.impl; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; import com.mr.li.service.Animal; @Primary @Component public class Dog implements Animal { @Override public void behavior() { System.out.println("汪汪汪~~~~~~~~~~"); } }
package com.mr.li.service.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import com.mr.li.service.Animal; import com.mr.li.service.Person; @Component public class Man implements Person { @Qualifier("cat") @Autowired private Animal animal; @Override public void behavior() { animal.behavior(); } }
4.user演示類
package com.mr.li.entity; import lombok.Data; @Data //@Component public class User { // @Value(value = "100") //這種直接賦值的優先級最高 private long id; // @Value(value = "章大狗") private String name; @Override public String toString() { return "id:"+ id + "name:" + name; } }
5.測試
package com.mr.li.test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import com.mr.li.config.AppConfig; import com.mr.li.entity.User; import com.mr.li.service.Person; import com.mr.li.service.impl.Man; import lombok.extern.slf4j.Slf4j; @Slf4j public class Test { public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); Person person = ctx.getBean(Man.class); person.behavior(); // User user = ctx.getBean(User.class); User user = ctx.getBean("user2", User.class); log.info("user:{}", user); } }
以上代碼的行爲:
AppConfg:掃描了定義的包,然後在身演示創建一些bean,可以看到同樣類型的bean給了不同的名稱,這些類對象在掃描後會被加載到ico容器中去,其中在ico中存儲的名稱就是指定的名稱,如果沒指定則使用方法名首字母小寫作爲名稱。
Man:人物類,他實現了Person接口,然後自身加了@Component被掃描註解,我們會發現它裏面有引入Animal類的,加了@Autowired註解,此註解就是通過ioc引入Animal的實現類對象,但他有2個實現類對象,所以需要指定到底使用哪個實現類作爲對象引入。三種方式:
第一種:直接將變量名animal改爲他的子類的類名即可,這個類名是ioc中的變量名,默認會將類首字母小寫,也可指定。
第二種:在需要引入的實現類上加@Primary註解,此註解意思是如果沒有特殊情況就加載他,但在兩個實現類上都加也不行,他的優先級小於@Qualifier註解。
第三種:@Qualifier註解,加載引入的類上同@Autowired一起存在,同樣需要指定ioc中存儲對應的變量名。
Test:演示了,創建一個ioc容器,加載是他內部的事,注意傳入加載的第一類即可。然後演示從ioc中取出對象並使用。