spring基本组件及注解
spring基本组件如上图:
spring配置文件
最初使用xml配置文件,然后转向注解。
//配置类====配置文件 @Configuration public class MainConfig { //给容器中注册一个bean, 类型为返回值的类型, //注意以@Bean注册bean,Id默认为方法名,也可通过@Bean注解的值来修改 @Bean public Person person01(){ return new Person("username",20); } } public class MainTest2 { public static void main(String args[]){ //加载注解的配置文件 ApplicationContext app = new AnnotationConfigApplicationContext(MainConfig.class); //从容器中获取bean //Person person = (Person) app.getBean("person01"); //System.out.println(person); String[] namesForBean = app.getBeanNamesForType(Person.class); for(String name:namesForBean){ System.out.println(name); } } }
@ComponentScan扫描规则
@Configuration @ComponentScan(value="com.enjoy.cap2", includeFilters={ @Filter(type=FilterType.ANNOTATION, classes={Controller.class}) }, useDefaultFilters=false) public class Cap2MainConfig { //给容器中注册一个bean, 类型为返回值的类型, @Bean public Person person01(){ return new Person("james",20); } }
- value的值说明是扫描此包下面的所有类
- includeFilters表示使用自定义的过滤器,此时useDefaultFilters应该为false屏蔽默认过滤器,自定义的才生效(demo中表示只扫描Controller类型的类)
- 另外的excludeFilters就是在默认过滤器下再过滤指定的类,自定义过滤器即可,implements
TypeFilter即可自定义
@ComponentScan value:指定要扫描的包
excludeFilters = Filter[] 指定扫描的时候按照什么规则排除那些组件
includeFilters = Filter[] 指定扫描的时候只需要包含哪些组件
useDefaultFilters = false 默认是true,扫描所有组件,要改成false
----扫描规则如下
FilterType.ANNOTATION:按照注解
FilterType.ASSIGNABLE_TYPE:按照给定的类型;比如按BookService类型
FilterType.ASPECTJ:使用ASPECTJ表达式
FilterType.REGEX:使用正则指定
FilterType.CUSTOM:使用自定义规则,自已写类,实现TypeFilter接口
//FilterType.CUSTOM的例子,常用
先新增自定义过滤规则类: TestTypeFilter
@ComponentScan(value="com.enjoy.cap2",includeFilters={
@Filter(type=FilterType.CUSTOM,classes={TestTypeFilter.class})
},useDefaultFilters=false)
@scope注解
spring中bean默认是单例singleton,@Scope(“prototype”)为多实例。
//多实例 @Scope("prototype") @Bean public Person person(){ return new Person("username",20); }
- prototype: 多实例:IOC容器启动并不会去调用方法创建对象放在容器中,而是
每次获取的时候才会调用方法创建对象 - singleton: 单实例(默认):IOC容器启动会调用方法创建对象放到IOC容器中
以后每交获取就是直接从容器(理解成从map.get对象)中拿 - request: 主要针对WEB应用,同一次请求创建一个实例
- session: 同一个session创建一个实例(主要掌握前面2个即可,后面2个了解)
lazy懒加载
@lazy当加入此注解时,则getBean调用的时候才会把实例加载到IOC容器。
@Conditional条件注册bean
public class WinCondition implements Condition{ /* *ConditionContext: 判断条件可以使用的上下文(环境) *AnnotatedTypeMetadata: 注解的信息 * */ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // TODO 是否为WINDOW系统 //能获取到IOC容器正在使用的beanFactory ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); //获取当前环境变量(包括我们操作系统是WIN还是LINUX??) Environment environment = context.getEnvironment(); String os_name = environment.getProperty("os.name"); if(os_name.contains("Windows")){ return true; } return false; } } //加入条件注解则会按自定义的逻辑注册,true时注册到容器 @Conditional(WinCondition.class) @Bean("lison") public Person lison(){ System.out.println("给容器中添加lison......."); return new Person("Lison",28); }
@Import注册bean
@Import(value = { Dog.class,Cat.class,JamesImportSelector.class,JamesImportBeanDefinitionRegistrar.class }) public class JamesImportSelector implements ImportSelector{ @Override public String[] selectImports(AnnotationMetadata importingClassMetadata){ //返回全类名的bean return new String[]{"com.enjoy.cap6.bean.Fish","com.enjoy.cap6.bean.Tiger"}; } } public class JamesImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /* *AnnotationMetadata:当前类的注解信息 *BeanDefinitionRegistry:BeanDefinition注册类 * 把所有需要添加到容器中的bean加入; * @Scope */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean bean1 = registry.containsBeanDefinition("com.enjoy.cap6.bean.Dog"); boolean bean2 = registry.containsBeanDefinition("com.enjoy.cap6.bean.Cat"); //如果Dog和Cat同时存在于我们IOC容器中,那么创建Pig类, 加入到容器 //对于我们要注册的bean, 给bean进行封装, if(bean1 && bean2){ RootBeanDefinition beanDefinition = new RootBeanDefinition(Pig.class); registry.registerBeanDefinition("pig", beanDefinition); } } }
给容器中注册组件的方式:
1,@Bean: [导入第三方的类或包的组件],比如Person为第三方的类, 需要在我们的IOC容器中使用
2,包扫描+组件的标注注解(@ComponentScan: @Controller, @Service @Reponsitory @
Componet),一般是针对 我们自己写的类,使用这个3,@Import:[快速给容器导入一个组件] 注意:@Bean有点简单
a,@Import(要导入到容器中的组件):容器会自动注册这个组件,bean 的 id为全类名
b,ImportSelector:是一个接口,返回需要导入到容器的组件的全类名数组
c,ImportBeanDefinitionRegistrar:可以手动添加组件到IOC容器, 所有Bean的注册可以使用BeanDifinitionRegistry,写JamesImportBeanDefinitionRegistrar实现ImportBeanDefinitionRegistrar接口即可- 4,使用Spring提供的FactoryBean(工厂bean)进行注册,实现FactoryBean<T>接口即可,在实现方法getObject里可写注册的实例。注意:如MyFactoryBean为实现了FactoryBean<T>接口,getBean("myFactoryBean")获取的实例为实现的getObject方法里的实例,getBean("&myFactoryBean")则为MyFactoryBean实例,具体逻辑查看源码可发现