Spring注解驱动开发系列:
Spring 组件注册
Spring Bean的生命周期
Spring属性赋值
Spring自动转配
Spring注解驱动开发之AOP
组件注册 @Configuration 声明这是一个配置类
在配置类中可以使用@Bean修饰方法,将该组件加入容器中。组件类型为返回值类型,组件id为方法名。
1 2 3 4 5 6 7 8 @Configuration public class SpringConfig { @Bean("people") public People people1 () { return new People ("ming" ,null ,null ); } }
@ComponentScan 开启组件扫描,将扫描范围中用@Component、@Repository、@Service、@Comtroller标注的类生成实例加入容器中。
@Repository、@Service、@Comtroller都继承@Component
1 2 3 4 5 6 7 8 9 10 11 12 13 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Repository { @AliasFor(annotation = Component.class) String value () default "" ; }
@ComponentScan使用
1 2 3 4 5 6 7 8 9 10 11 12 @ComponentScan( basePackages = {"south.block"}, includeFilters ={ @ComponentScan.Filter(type = FilterType.ANNOTATION, value = { Service.class, Repository.class }) }, useDefaultFilters = false, excludeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = UserService.class ) } )
@ComponentScan( basePackages = {“south.block”} ) 或者@ComponentScan( value = {“south.block”} ) 指定要扫描的包。
includeFilters 是一个 Filter[] ,表示包括的类型,可以使用注解类型、指定的类型、正则表达式、AspectJ表达式、自定义类等。但是,默认会开启一个默认的扫描所有的被@Component、@Repository、@Service、@Comtroller标注的类的过滤器,因此我们通常需要使用useDefaultFilters = false关闭
excludeFilters 也是一个 Filter[] ,表示排除的类型,同上
在设置包括或排除过滤器时,我们如果使用根据注解类型排除需要注意@Component与@Repository、@Service、@Comtroller的包括关系
自定义TypeFilter
上面代码中,我们的排除过滤器规则是自定义实现TypeFilter接口的一个类
我们可以获取类的元信息,自定义匹配规则,包含或排除一些组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class scanFilter implements TypeFilter { public boolean match (MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { Resource resource = metadataReader.getResource(); AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); ClassMetadata classMetadata = metadataReader.getClassMetadata(); String className = classMetadata.getClassName(); boolean isEr = className.contains("er" ); return isEr; } }
@Scope 使用@Scope注解来表示组件的作用域
基础的有两种,singleton和prototype,分别表示单例和多例
Web环境中,还有request和session,分别表示每个请求对应一个和每个session对应一个
单例默认是在容器创建的时候直接创建
多例则默认不会
@Lazy() 我们使用@Lazy()来设置组件是否懒加载,默认true
@Lazy(false)则表示非懒加载,也就是容器创建时就生成对象
@Lazy(true)则表示懒加载,只有在用时才会去创建对象
@Conditional 可以修饰类或方法,修饰类表示条件满足时,才会将这个类中的组件加入容器。修饰方法表示条件满足时,才会将方法表示的组件加入容器
@Conditional()其中传入一个Condition实现类的Class对象集合
如下,表示window系统创建bill对象,linux系统创建linux对象
1 2 3 4 5 6 7 8 9 10 11 @Conditional({ WinCondition.class }) @Bean public People linux () { return new People ("linux" ,null ,null ); } @Conditional({ Linux.class }) @Bean public People bill () { return new People ("bill" ,null ,null ); }
其中,WinCondition类如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class WinCondition implements Condition { public boolean matches (ConditionContext context, AnnotatedTypeMetadata metadata) { BeanDefinitionRegistry registry = context.getRegistry(); ResourceLoader resourceLoader = context.getResourceLoader(); ClassLoader classLoader = context.getClassLoader(); ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); Environment environment = context.getEnvironment(); String os = environment.getProperty("os.name" ); if (os.contains("Windows" )){ return true ; } return false ; } }
LinuxCondition类似省略
@Import 加在类上,将组件快速导入容器中
可以加类的Class对象,如:@Import(Cat.class)表示将Cat类加入容器中,组件名为类的全路径名
可以加一个ImportSelector的实现类,返回需要添加组件的全类名
可以加一个ImportBeanDefinitionRegistrar的实现类,直接在其方法中注册组件
使用@Import导入
1 @Import({Cat.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
ImportSelector实现类
1 2 3 4 5 6 7 8 9 10 public class MyImportSelector implements ImportSelector { public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String []{"south.block.pojo.User" }; } }
ImportBeanDefinitionRegistrar实现类
1 2 3 4 5 6 7 8 9 10 11 12 public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { public void registerBeanDefinitions (AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean existPeople2 = registry.containsBeanDefinition("people2" ); if (existPeople2) { RootBeanDefinition rootBeanDefinition = new RootBeanDefinition (User.class); registry.registerBeanDefinition("userRegistrar" ,rootBeanDefinition); } } }
FactoryBean 其实更像一个工厂,用于生产某种Bean
自定义类实现FactoryBean接口即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class ColorFactory implements FactoryBean <Color> { public Color getObject () throws Exception { return new Color (); } public Class<?> getObjectType() { return Color.class; } public boolean isSingleton () { return true ; } }
从容器中获取ColorFactory实例时,会去调用getObject()方法获取Color实例对象。当然如果是单例模式,则并不会每次都去调用getObject()方法
如果我们想要从容器中获取ColorFactory对象时,可以在bean名称前加一个&,例如想要获取ColorFactory对象,Object bean = context.getBean(“&colorFactory”);