本篇博客主要参考了【路人甲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是错误的