本篇博客主要參考了【路人甲Java】系列博文的《Spring高手系列》的學習指導思路,進行的編碼和測試。
本文最后更新於:2022年03月06日
1. 引言
Srping時bean的管理容器。批量注冊bean是Spring的基本操作。
Spring批量注冊bean的方式有2種:
- @ComponentScan和@ComponentScans
- @Import
2. @ComponentScan(s)批量注冊
2.1 @ComponentScan
@ComponentScan用於批量注冊bean。該注解會讓spring去掃描【某些包以及其子包內的所有的類】,然后【將滿足一定條件的類作為bean】注冊到容器中。
從這句話可以看出幾個重點:
- @ComponentScan掃描的是包,子包里面的所有類。這就需要確認掃描哪些包。確認包的方式有兩種:
- 按照包名。也就是指定直接確認包名。
- 按照類名。也就是通過類名來間接確認包名。
- 將滿足一定調節的類作為bean注冊到容器。這就需要通過某些調節來確認目標bean:
- useDefaultFilters默認過濾。有某些注解的類,可以作為bean注冊。比如:@Component,@Controller,@Service,@Repository
- includeFilters白名單過濾。
- excludeFilters黑名單過濾。
@ComponentScan可以通過value或者basePackage來配置要掃描的包。通過value掃描時,使用方法如下:
@ComponentScan({"package01","package02"})
這樣就可以把package01和package02包內的類注冊為bean。
注意:通過這樣指定包名掃描,有一個隱患:若包被重命名了,會導致掃描失效。
所以一般情況下,我們使用basePackageClasses的方式來指定掃描的包,該參數可以指定一些類型,默認會掃描這些類所在的包及其子包中所有的類,這種方式可以有效避免這種問題。
2.2 @includeFilters
2.2.1 掃描包含注解的類
如上所述,該注解通過一個Filter類型的數組,存放要被掃描的類。它作為@CompoentScan的一個參數使用。
使用方法如下:
@ComponentScan(
useDefaultFilters = false; //默認是true
includeFilters = {
@ComponentScan.Filter(type=FilterType.ANNOTATION,classes=自定義注解)
}
)
通過includeFilters可以注冊自定義注解。但是這種自定義注解無法指定bean的名稱。
通過對自定義注解的改造,可以完成自定義bean能夠指定bean的名稱。
2.2.2 包含指定類型的類
使用方法如下:
@ComponentScan(
useDefaultFilters = false; //默認是true
includeFilters = {
@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,classes=自定義類型.class)
}
)
這樣,被掃描的滿足【自定義類型.class.isAssignableFrom】條件的都會被注冊
2.3 自定義Filter
2.3 練習代碼
源碼目錄:/root/liwldev/java/web/springframe/SpringAnnotation/src/main/java/com/liwl/dev
- Person.Java 接口
- PersonImpl.java 實現類
- School.java 接口
- SchoolImpl.java 實現類
- SpringConfig.java 配置類
測試目錄:/root/liwldev/java/web/springframe/SpringAnnotation/src/test/java/com/liwl/dev
- MyTest.java
其他:
- 刪除bean.xml,完全使用注解來配置
- 保留all.properties外部屬性配置文件
2.3.1 @ComponentScan注解和@Component注解
這小節練習@Component注解。
使用該注解的類都會注冊到spring里面,bean的名稱需要通過@Component(value = "bean名稱")來指定。如果不指定,則是以【首字母小寫的類名】作為bean的名稱。
PersonImpl.java
package com.liwl.dev;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@PropertySource(value = {"classpath:all.properties"},encoding = "utf-8")
@Component
public class PersonImpl implements Person {
@Value(value = "${liwl_name}")
private String name;
@Value(value = "${liwl_age}")
private int age;
@Autowired
private School school; //這里沒有使用@Qualifier注解
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "PersonImpl->" + "name:" + name + ",age:" + age + ",school:" + school;
}
}
SchoolImpl.java
package com.liwl.dev;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class SchoolImpl implements School {
@Value(value = "${school_name}")
private String name;
@Value(value = "${school_address}")
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "SchoolImpl->" + "name:" + name + ",address:" + address;
}
}
SpringConfig.java
package com.liwl.dev;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class SpringConfig {
public void showMe(){
System.out.println("我是配置類的showMe方法");
}
}
MyTest.java代碼
package com.liwl.dev;
import java.util.Arrays;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
for(String beanName: context.getBeanDefinitionNames()){
String[] aliases = context.getAliases(beanName);
System.out.println(String.format("bean名稱:%s,別名:%s,bean對象:%s", beanName,Arrays.asList(aliases),context.getBean(beanName)));
}
((ConfigurableApplicationContext) context).close();
}
}
F5運行MyTest.java結果
...
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$60335662@65c7a252
bean名稱:personImpl,別名:[],bean對象:PersonImpl->name:"liwl",age:30,school:SchoolImpl->name:"江南",address:"無錫"
bean名稱:schoolImpl,別名:[],bean對象:SchoolImpl->name:"江南",address:"無錫"
然后@Component通過value設置bean名稱
//代碼片段
@Component(value = "liwl")
public class PersonImpl implements Person {
...;
}
//SchoolImpl.java代碼片段
@Component(value = "school")
public class SchoolImpl implements School {
...;
}
F5運行MyTest.java結果
...
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$60335662@65c7a252
bean名稱:liwl,別名:[],bean對象:PersonImpl->name:"liwl",age:30,school:SchoolImpl->name:"江南",address:"無錫"
bean名稱:school,別名:[],bean對象:SchoolImpl->name:"江南",address:"無錫"
可以看到bean名稱已經對應設置。
這里有個奇怪的問題:
PersonImpl.java里面,PersonImpl對School依賴時,直接通過@Autowired使得School類型bean自動注入即可,不需要@Qualifiler,加上也無妨。這個跟之前一個練習試驗不一樣。記錄於2022年03月02日。
2.3.2 @ComponentScan注解和@Controller,@Service,@Repository
@Controller,@Service,@Respository這三個注解實際上區別不大。只是在代碼框架邏輯上進行的人為區別。
修改PersonImpl.java代碼,把注解@Component換成@Controller
package com.liwl.dev;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
@PropertySource(value = {"classpath:all.properties"},encoding = "utf-8")
@Controller(value = "liwl")
public class PersonImpl implements Person {
@Value(value = "${liwl_name}")
private String name;
@Value(value = "${liwl_age}")
private int age;
@Autowired
@Qualifier(value = "school")
private School school;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "PersonImpl->" + "name:" + name + ",age:" + age + ",school:" + school;
}
}
修改SchoolImpl.java
package com.liwl.dev;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@Service(value = "school")
public class SchoolImpl implements School {
@Value(value = "${school_name}")
private String name;
@Value(value = "${school_address}")
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "SchoolImpl->" + "name:" + name + ",address:" + address;
}
}
F5運行結果
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$376ebf8@6340e5f0
bean名稱:liwl,別名:[],bean對象:PersonImpl->name:"liwl",age:30,school:SchoolImpl->name:"江南",address:"無錫"
bean名稱:school,別名:[],bean對象:SchoolImpl->name:"江南",address:"無錫"
總結,上面可以看出實際上被其他注解標注的類,都被當做bean加載到容器里面,並無區別。
2.3.3 @Component掃描指定的包
在@Component注解源碼能夠看到其被@Repeatable(ComponentScans.class)注解,說明@Component注解能夠同時使用多個。
通過以下三個參數來指定要掃描哪些包:
- value = String
- basePackages = String[]
- basePackageClasses
通過value或者basePackages。value值是字符串,basePackages是字符串數組
通過以下方式來指定要掃描的包
//方式一:
@Component(value = "package")
//方式二:
@Component(basePackages={
"package001",
"package002"
})
//方式三:
@Component(basePackageClasses = "自定義類型")
首先在源碼目錄/root/liwldev/java/web/springframe/SpringAnnotation/src/main/java/com/liwl/dev
下創建三個目錄
- controller
- LiwlController.java
- service
- LiwlService.java
- dao
- LiwlDao.java
LiwlController.java源碼里面使用注解@Controller,如下:
package com.liwl.dev.controller;
import org.springframework.stereotype.Controller;
@Controller
public class LiwlController {
}
LiwlService.java源碼里面使用注解@Service,如下:
package com.liwl.dev.service;
import org.springframework.stereotype.Service;
@Service
public class LiwlService {
}
LiwlDao.java源碼里面使用注解@Repository,如下:
package com.liwl.dev.dao;
import org.springframework.stereotype.Repository;
@Repository
public class LiwlDao {
}
然后修改SpringConfig.java,采用value參數形式
package com.liwl.dev;
import com.liwl.dev.controller.ScanClassToBean;
import com.liwl.dev.dao.ScanClassToBean01;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(value = "com.liwl.dev")
public class SpringConfig {
}
F5運行MyTest.java結果
...
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$6f9fd2da@47af7f3d
bean名稱:liwl,別名:[],bean對象:PersonImpl->name:"liwl",age:30,school:SchoolImpl->name:"江南",address:"無錫"
bean名稱:school,別名:[],bean對象:SchoolImpl->name:"江南",address:"無錫"
bean名稱:liwlController,別名:[],bean對象:com.liwl.dev.controller.LiwlController@7c729a55
bean名稱:liwlDao,別名:[],bean對象:com.liwl.dev.dao.LiwlDao@3bb9a3ff
bean名稱:liwlService,別名:[],bean對象:com.liwl.dev.service.LiwlService@661972b0
修改SpringConfig.java,采用basePackages參數形式
package com.liwl.dev;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages={
"com.liwl.dev.controller",
"com.liwl.dev.service"
})
public class SpringConfig {
public void showMe(){
System.out.println("我是配置類的showMe方法");
}
}
F5運行MyTest.java,結果如下:
...
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$cec403aa@6cd28fa7
bean名稱:liwlController,別名:[],bean對象:com.liwl.dev.controller.LiwlController@614ca7df
bean名稱:liwlService,別名:[],bean對象:com.liwl.dev.service.LiwlService@4738a206
可見:
當通過注解@ComponentScan指定要掃描的包時,spring里面注冊的bean,就是指定包里面的類對象,以【首字母小寫的類名】作為bean的名稱。
注意:
指定包名來確認要注冊的bean,存在一個問題。當包名被重命名之后,會導致掃描包失敗。因此一般情況下,使用basePackageClasses的方式來指定要掃描的包。
通過basePackageClasses
使用value或者basePackages來指定要掃描的包時,會因為包名的變化導致掃描失敗。basePackageClasses的指定方式,能夠解決此類問題。它通過掃描參數指定的類型(自定義類型,接口)所在的包以及其子包中所有的類,來避免包名變化導致無法掃描的問題。
因為注解@ComponentScan被@Repeatable注解,所以使用basePackageClasses時,必須通過多重注解的方式添加分布在等級包名下的自定義類型。
在目錄/root/liwldev/java/web/springframe/SpringAnnotation/src/main/java/com/liwl/dev/controller
下創建ScanClassToBean.java
package com.liwl.dev.controller;
public interface ScanClassToBean {
}
在目錄/root/liwldev/java/web/springframe/SpringAnnotation/src/main/java/com/liwl/dev/service
下創建ScanClassToBean01.java
package com.liwl.dev.dao;
public interface ScanClassToBean01 {
}
修改SpringConfig.java
package com.liwl.dev;
import com.liwl.dev.controller.ScanClassToBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackageClasses = ScanClassToBean.class)
public class SpringConfig {
}
F5運行MyTest.java結果如下
...
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$46d705db@4c9f8c13
bean名稱:liwlController,別名:[],bean對象:com.liwl.dev.controller.LiwlController@5ae50ce6
修改SpringConfig.java
package com.liwl.dev;
import com.liwl.dev.controller.ScanClassToBean;
import com.liwl.dev.service.ScanClassToBean01;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackageClasses = ScanClassToBean.class)
@ComponentScan(basePackageClasses = ScanClassToBean01.class)
public class SpringConfig {
}
F5運行MyTest.java結果如下
...
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$a25f16fb@5bd03f44
bean名稱:liwlController,別名:[],bean對象:com.liwl.dev.controller.LiwlController@29626d54
bean名稱:liwlService,別名:[],bean對象:com.liwl.dev.service.LiwlService@5a63f509
2.3.4 includeFilters使用
1. 指定包含指定注解的類
在目錄/root/liwldev/java/web/springframe/SpringAnnotation/src/main/java/com/liwl/dev
下創建annotation
目錄
在目錄/root/liwldev/java/web/springframe/SpringAnnotation/src/main/java/com/liwl/dev/annotation
下創建LiwlAnnotation.java
package com.liwl.dev.annotation;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface LiwlAnnotation{
}
修改LiwlDao.java
package com.liwl.dev.dao;
import com.liwl.dev.annotation.LiwlAnnotation;
import org.springframework.stereotype.Repository;
@Repository
@LiwlAnnotation
public class LiwlDao {
}
修改SpringConfig.java
package com.liwl.dev;
import com.liwl.dev.annotation.LiwlAnnotation;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
@Configuration
@ComponentScan(
includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = LiwlAnnotation.class)
})
public class SpringConfig {
}
F5運行MyTest.java結果
...
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$f8c8671a@3e58a80e
bean名稱:liwl,別名:[],bean對象:PersonImpl->name:"liwl",age:30,school:SchoolImpl->name:"江南",address:"無錫"
bean名稱:school,別名:[],bean對象:SchoolImpl->name:"江南",address:"無錫"
bean名稱:liwlController,別名:[],bean對象:com.liwl.dev.controller.LiwlController@4fb61f4a
bean名稱:liwlDao,別名:[],bean對象:com.liwl.dev.dao.LiwlDao@4fb0f2b9
bean名稱:liwlService,別名:[],bean對象:com.liwl.dev.service.LiwlService@79924b
從上面運行結果發現,所有類都被注冊為bean。為什么includeFilters參數沒有生效?這是因為@ComponentScan有一個參數useDefaultFilters
,該參數默認是true,修改為false,再觀察結果。
修改SpringConfig.java
package com.liwl.dev;
import com.liwl.dev.annotation.LiwlAnnotation;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
@Configuration
@ComponentScan(
useDefaultFilters = false,
includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = LiwlAnnotation.class)
})
public class SpringConfig {
}
F5運行MyTest.javaJ結果
....
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$c34b74e6@6a400542
bean名稱:liwlDao,別名:[],bean對象:com.liwl.dev.dao.LiwlDao@6580cfdd
從上面運行結果發現,之后標准了注解@LiwlAnnotation的類LiwlDao,才會被注冊到spring里面
在上面的自定義注解@LiwlAnnotation里面,無法自定義bean的名稱。下面通過改造該注解,使其具備自定義bean的功能。
修改LiwlAnnotation.java
package com.liwl.dev.annotation;
import java.lang.annotation.*;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface LiwlAnnotation{
@AliasFor(annotation = Component.class)
String value() default "";
}
修改LiwlDao.java
package com.liwl.dev.dao;
import com.liwl.dev.annotation.LiwlAnnotation;
import org.springframework.stereotype.Repository;
@Repository
@LiwlAnnotation(value = "liwldao")
public class LiwlDao {
}
F5運行MyTest.java
...
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$4ba0f5e7@1700915
bean名稱:liwldao,別名:[],bean對象:com.liwl.dev.dao.LiwlDao@21de60b4
從運行結果能夠看出,spring已經注冊了名為liwldao的bean
2. 指定包含指定類型的類
修改SpringConfig.java
package com.liwl.dev;
import com.liwl.dev.service.LiwlService;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
@Configuration
@ComponentScan(
useDefaultFilters = false,
includeFilters = {
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = LiwlService.class)
})
public class SpringConfig {
}
F5運行MyTest.java結果如下
...
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$776b2c0c@c267ef4
bean名稱:liwlService,別名:[],bean對象:com.liwl.dev.service.LiwlService@30ee2816
從結果可以看出,spring只注冊了LiwlService的bean。
2.3.5 自定義過濾器
本部分待補充
2.3.6 @ComponentScans重復使用
@ComponentScan在定義中使用了@Repeatable注解,表示該注解可以重復使用。一般使用方式如下:
@ComponentScan(backPacagekClasses = 自定義類型.class)
@ComponentScan(
useDefaultFilters = false,
includeFilters = {
@CompontScan.Filter(type=Filter.Type.ASSIGNABLE_TYPE,classes=自定義類)
})
或者
@ComponentScans({
@ComponentScan(backPacagekClasses = 自定義類型.class)
@ComponentScan(
useDefaultFilters = false,
includeFilters = {
@CompontScan.Filter(type=Filter.Type.ASSIGNABLE_TYPE,classes=自定義類)
})})
3. @Import
@Import注解跟xml配置的<import>
標簽作用一樣,允許通過它引入:
- @Configuration標注的類
- ImportSelector接口和ImportBeanDefinitionRegistrar接口實現
- @Component注解的普通類
總的來說:@Import可以用來批量導入需要注冊的各種類,普通類,配置類,完成bean的注冊。
@Import的參數value常見的5種用法
- value為普通的類
- value為@Configuration標注的類
- value為@ComponetentScan標注的類
- value為ImportBeanDefinionRegistart接口類型
- value為ImportSelector接口類型
- value為DeferredImportSelector接口類型
3.1 value為普通的類
修改SpringConfig.java
package com.liwl.dev;
import com.liwl.dev.dao.LiwlDao;
import com.liwl.dev.service.LiwlService;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@ComponentScan(value = "com.liwl.dev.controller")
public class SpringConfig {
}
修改MyTest.java
package com.liwl.dev;
import java.util.Arrays;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
System.out.println("\n...");
for(String beanName: context.getBeanDefinitionNames()){
String[] aliases = context.getAliases(beanName);
if(beanName.contains("org.springframework")){
continue;
}
System.out.println(String.format("bean名稱:%s,別名:%s,bean對象:%s", beanName,Arrays.asList(aliases),context.getBean(beanName)));
}
((ConfigurableApplicationContext) context).close();
}
}
修改LiwlService.java和LiwlDao.java,去掉全部在注解,變為普通類
package com.liwl.dev.dao;
import com.liwl.dev.annotation.LiwlAnnotation;
import org.springframework.stereotype.Repository;
public class LiwlDao {
}
package com.liwl.dev.service;
import org.springframework.stereotype.Service;
public class LiwlService {
}
F5運行MyTest.java結果如下
...
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$e5da1911@35047d03
bean名稱:liwlController,別名:[],bean對象:com.liwl.dev.controller.LiwlController@49b0b76
從結果可以發現,只有liwlController的bean注冊到了spring容器里。
修改SpringConfig.java
package com.liwl.dev;
import com.liwl.dev.dao.LiwlDao;
import com.liwl.dev.service.LiwlService;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@ComponentScan(value = "com.liwl.dev.controller")
@Import({LiwlService.class,LiwlDao.class})
public class SpringConfig {
}
F5運行MyTest.java結果如下
...
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$6fa9b108@e056f20
bean名稱:liwlController,別名:[],bean對象:com.liwl.dev.controller.LiwlController@4b0b0854
bean名稱:com.liwl.dev.service.LiwlService,別名:[],bean對象:com.liwl.dev.service.LiwlService@19bb07ed
bean名稱:liwldao,別名:[],bean對象:com.liwl.dev.dao.LiwlDao@10e41621
從結果可以看出,已經通過@Import注解,向spring容器注冊了普通的類LiwlService和LiwlDao
此時也可以在要被注冊的LiwlService上使用注解@Compoent(value="xxx")的方式,為bean指定名稱,比如:
修改LiwlService.java
package com.liwl.dev.service;
import org.springframework.stereotype.Service;
@Service(value = "liwlservice")
public class LiwlService {
}
F5運行結果
...
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$6f60a7f@17046283
bean名稱:liwlController,別名:[],bean對象:com.liwl.dev.controller.LiwlController@5bd03f44
bean名稱:liwlservice,別名:[],bean對象:com.liwl.dev.service.LiwlService@29626d54
bean名稱:com.liwl.dev.dao.LiwlDao,別名:[],bean對象:com.liwl.dev.dao.LiwlDao@5a63f509
從運行結果發現,此時已經給LiwlService要注冊的bean,設置了名稱liwlservice
總結:
按照模塊的方式進行導入,需要哪個某塊就導入那個某塊,不需要的時候,直接修改一下總的配置類,調整@Import的value就可以了。
3.2 value為@Configuration標注的配置類
這種情況主要發生在項目很大時,需要划分很多模塊,會按照模塊獨立開發,每個某塊在maven中表現為一個個構建,然后通過坐標的方式引入需要引入的模塊。
假如項目中有2個模板,2個模塊都有各自的配置類。
在目錄/root/liwldev/java/web/springframe/SpringAnnotation/src/main/java/com/liwl/dev
下創建config目錄
在config目錄下創建SpringSubConfig01.java和SpringSubConfig02.java文件
修改SpringSubConfig01.java
package com.liwl.dev.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringSubConfig01 {
@Bean(value = "sprintsubconfig01_show")
public String show(){
return "我是SpringSubconfig01配置類";
}
}
修改SpringSubConfig02.java
package com.liwl.dev.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringSubConfig02 {
@Bean(value = "springsubconfig02_show")
public String show(){
return "我是SpringSubConfig02配置類";
}
}
修改主配置文件SpringConfig.java
package com.liwl.dev;
import com.liwl.dev.config.SpringSubConfig01;
import com.liwl.dev.config.SpringSubConfig02;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({SpringSubConfig01.class,SpringSubConfig02.class})
public class SpringConfig {
}
F5運行MyTest.java結果
...
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$7afc888b@6193932a
bean名稱:com.liwl.dev.config.SpringSubConfig01,別名:[],bean對象:com.liwl.dev.config.SpringSubConfig01$$EnhancerBySpringCGLIB$$402ae426@647fd8ce
bean名稱:sprintsubconfig01_show,別名:[],bean對象:我是SpringSubconfig01配置類
bean名稱:com.liwl.dev.config.SpringSubConfig02,別名:[],bean對象:com.liwl.dev.config.SpringSubConfig02$$EnhancerBySpringCGLIB$$788d8747@159f197
bean名稱:springsubconfig02_show,別名:[],bean對象:我是SpringSubConfig02配置類
從結果可以看出,2個模塊的子配置類,已經成功導入主配置,並且注冊到spring容器。
3.3 value為@ComponentScan標注的類
在目錄/root/liwldev/java/web/springframe/SpringAnnotation/src/main/java/com/liwl/dev/controller
下創建LiwlScanClass01.java
package com.liwl.dev.controller;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
public class LiwlScanClass01 {
}
在目錄/root/liwldev/java/web/springframe/SpringAnnotation/src/main/java/com/liwl/dev/service
下創建LiwlScanClass02.java
package com.liwl.dev.service;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
public class LiwlScanClass02 {
}
修改SpringConfig.java
package com.liwl.dev;
import com.liwl.dev.controller.LiwlScanClass01;
import com.liwl.dev.service.LiwlScanClass02;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({LiwlScanClass01.class,LiwlScanClass02.class})
public class SpringConfig {
}
F5運行結果
...
bean名稱:springConfig,別名:[],bean對象:com.liwl.dev.SpringConfig$$EnhancerBySpringCGLIB$$3a9f6330@29626d54
bean名稱:liwlController,別名:[],bean對象:com.liwl.dev.controller.LiwlController@5a63f509
bean名稱:liwlservice,別名:[],bean對象:com.liwl.dev.service.LiwlService@6e4784bc
bean名稱:com.liwl.dev.controller.LiwlScanClass01,別名:[],bean對象:com.liwl.dev.controller.LiwlScanClass01@34b7ac2f
bean名稱:com.liwl.dev.service.LiwlScanClass02,別名:[],bean對象:com.liwl.dev.service.LiwlScanClass02@e056f20
從運行結果來看,已經成功注冊了了包controller和包service包的類。
目錄下的接口未注冊,並且接口使用@ComponentScan是錯誤的