@Component:通用注解组件,可被继承扩展为不同层次使用的专用组件.当某一个类在不属于其他典型层次中可作为选择使用
@Controller: 控制层,所注解的为Controller类型与最前端用户数据交互,在web 中广泛与RequestMapping等结合使用
@Service: 服务层,所注解的为一般业务类(如xxxServiceImpl…),负责处理某一类问题的服务.上承控制层数据;处理业务逻辑;下接数据层适配转换
@Repository:数据层,所注解的为最底层与数据直接打交道的类,提供CRUD基本API,以及额外的持久化等功能.一般表现形式为xxxDAO,xxxRepository等,在spring-data模块中有很多,与各类数据库及框架等有很好的适配
@Indexed:不属于任何层,与其他类注解结合用作提升spring扫面注解装配性能的一种索引模式.
@Configuration:加载配置类,通过AnnotationConfigApplicationContext可以注册、扫描并创建符合条件的实例.类本身也作为一个bean被放入容器中存在
空壳配置类:与@ComponentScan,@ComponentScans等结合使用,通过扫描package的方式筛选出需要的bean。该配置类中不需要作任何定义bean的行为,通过AnnotationConfigApplicationContext传递scan的package给spring扫描。
@Configuration
@ComponentScan("com.example.spring1")
public class AppConfig {
}
引入配置类:与@Import结合使用。可直接引入类(beanName为全路径名,需要可被构造:要么无参构造,要么注入所需构造参数到容器);通过ImportSelector接口导入类名注入;
Import{ModelA.class}: com.example.spring2.external.ModelA:com.example.spring2.external.ModelA@2eae8e6e
Import{ModelImportSelector.class}:
com.example.spring2.external.SelectorModel:com.example.spring2.external.SelectorModel@8f2ef19
Import{ModelImportBeanDefinitionRegistrar.class}:
registerModel:com.example.spring2.external.RegistrarModel@25ce9dc4
@Configuration
@Import({
ModelA.class,ModelImportSelector.class,ModelImportBeanDefinitionRegistrar.class})
public class AppConfig {
@Bean
@Primary
public DemoService demoService(){
return new DemoService(); }
@Bean(initMethod = "init",destroyMethod = "destroy")
@Conditional(value = {
BeanCreatorCodition.class})
public DemoController demoController(){
return new DemoController(demoService());
}
@Bean
public String modelAName(){
return "modelA_name"; }
}
public class ModelA {
private String name;
public ModelA(String name){
this.name =name;
}
}
public class SelectorModel {
private String name;
}
// custom import component
public class ModelImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{
SelectorModel.class.getName()};
}
}
public class ModelImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
RootBeanDefinition rbd =new RootBeanDefinition(RegistrarModel.class);
//register beanDefinition to IOC with given beanName
beanDefinitionRegistry.registerBeanDefinition("registerModel",rbd);
}
}
定义配置类:当应用中其他需要被注入的bean没有加类注解(component等)时,可以统一在该配置类中定义所有需要注入的bean[一般为第三方类]。
@Configuration
public class AppConfig {
@Bean
@Primary
@DependsOn({
"demoDAO"})
public DemoService demoService(){
return new DemoService();
}
@Bean(initMethod = "init",destroyMethod = "destroy")
@Conditional(value = {
BeanCreatorCodition.class})
public DemoController demoController(){
return new DemoController(demoService());
}
@Bean
public DemoDAO demoDAO(){
return new DemoDAO();
}
}
public class BeanCreatorCodition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//get property/profile from environment
Environment environment = conditionContext.getEnvironment();
//get bean info from beanFactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
//get annotated attribute info from AnnotatedTypeMetadata, created the bean if initMethod specified
//get value;name;autowire;autowireCandidate;initMethod;destroyMethod;
Map<String, Object> attributes = annotatedTypeMetadata.getAnnotationAttributes(Bean.class.getName());
if (attributes.get("initMethod")!=null){
return true;
}
return false;
}
}
@ComponentScan/@ComponentScans:定义需要扫描注解的bean包路径,同时可以自定义过滤规则排除或选择某些类作为最后进入容器的对象[需要disable默认filter—>useDefaultFilters = false].
enum FilterType:
ANNOTATION,
ASSIGNABLE_TYPE,
ASPECTJ,
REGEX,
CUSTOM
@Configuration
@ComponentScan(value = {
"com.example.spring3"},
includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {
Controller.class, CustomAnno.class}),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {
AbstractService.class}),
@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {
CustomFilter.class})
},excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {
Controller.class})},
useDefaultFilters = false)
public class AppConfig {
}
自定义扩展注解:CustomAnno,通过添加FilterType.ANNOTATION将该注解的类扫描进去
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CustomAnno {
}
自定义实现ComponentScan.Filter: CustomFilter ,实现TypeFilter接口将Repository类型的类扫描进去
public class CustomFilter implements TypeFilter {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
Set<String> annotationTypes = annotationMetadata.getAnnotationTypes();
if (annotationTypes.contains(Repository.class.getName())){
return true;
}
return false;
}
}
条件同时命中excludeFilters和includeFilters时,excludeFilters优先成为最后注入的条件判断,例如该测试中Controller类型的并未注入到容器中
appConfig:com.example.spring3.config.AppConfig$$EnhancerBySpringCGLIB$$b86ebffd@78e4deb0
demoDAO:com.example.spring3.dao.DemoDAO@6e9175d8
customAnnotatedModel:com.example.spring3.model.CustomAnnotatedModel@7d0b7e3c
extendsService:com.example.spring3.service.ExtendsService@15bb5034
@Autowired
当容器中有同类型的多个bean时,Autowired优先查找@Primary修饰的;同时容器中按类型查找时也按此优先查找
配合 @Qualifier(“demoServiceB”)使用时,按beanName从容器找符合的bean, Primary修饰失效
可设置required属性,需要注入的依赖对象可不存在容器中
public class DemoController {
@Autowired
private DemoService demoService1; //DemoServiceA
@Autowired
@Qualifier("demoServiceB")
private DemoService demoService2;//DemoServiceB
@Resource(name = "demoServiceB")
private DemoService demoService3;//DemoServiceB
public void print(){
System.out.println("controller invoke...");
demoService1.print();
demoService2.print();
demoService3.print();
}
}
@Resource–>javax.annotation.Resource
@Configuration
@ComponentScan("com.example.spring4")
public class AppConfig {
@Bean
public DemoController demoController(){
return new DemoController(); }
@Bean("demoService")
@Primary
public DemoService demoService(){
return new DemoServiceA(); }
@Bean("demoServiceB")
public DemoService demoServiceB(){
return new DemoServiceB(); }
}
注:Autowired和Resource对于同类型的多个实现类在容器中时,可以以Map形式注入
public class DiffController {
@Autowired
private Map demoServiceAutowire;
@Resource
private Map demoServiceMapResource;
public void print(){
System.out.println("controller invoke...");
System.out.println(demoServiceAutowire);
System.out.println(demoServiceMapResource);
}
}
其中两中形式注入结果一样,beanName->bean
{demoService=com.example.spring4.service.DemoServiceA@17f9d882, demoServiceB=com.example.spring4.service.DemoServiceB@79e4c792}
{demoService=com.example.spring4.service.DemoServiceA@17f9d882, demoServiceB=com.example.spring4.service.DemoServiceB@79e4c792}
demo 地址: github