1spring注解:@Configuration,@Bean,@ComponentScan(),@Scope
传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事物,这么做有两个缺点:
1、如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么.xml文件又会非常多。总之这将导致配置文件的可读性与可维护性变得很低。
2、在开发中在.java文件和.xml文件之间不断切换,是一件麻烦的事,同时这种思维上的不连贯也会降低开发的效率。
为了解决这两个问题,Spring引入了注解,通过"@XXX"的方式,让注解与Java Bean紧密结合,既大大减少了配置文件的体积,又增加了Java Bean的可读性与内聚性。
所有的注解都是在一个工程中进行演示、后面不懂得可以参考前面的随笔!
开始注解的代码编程:
1.工程准备
Person.class
public class Person { private String name; private int age; ... }
配置类:
Config.class
//配置类 === 配置文件xxx.xml //@Configuration是告诉Spring这是一个配置类 @Configuration public class Config { //给容器注册一个bean,相当于配置文件的 <bean></bean> //类型默认是返回的类型 //id默认是方法名 @Bean("per") public Person person(){ return new Person("MrChengs",20); } }
测试:
ApplicationContext app = new AnnotationConfigApplicationContext(Config.class); Person p =app.getBean(Person.class); System.out.println(p);
Person [name=MrChengs, age=20]
1.@Configuration
告诉sprin该类是一个配置类
所谓的配置类相当于我们所写的xxx.xml配置文件
2.@Bean
给容器中注入一个Bean,相当于<bean></bean>进行实例化一个bean
属性:
默认value可以不写
3.@ComponentScan()
等同于:<context:component-scan base-package=""></context:component-scan>
新建四个类,分别使用:@Repository,@Service,@Controller三个注解
@Repository public class CustomerDao { }
@Service public class CustomerService { }
@Controller public class CustomerConteoller { }
在Config.class类中
@Configuration @ComponentScan(value="coom.MrChengs.config",excludeFilters={ @Filter(type=FilterType.ANNOTATION,classes={Repository.class})}) public class Config { @Bean("per") public Person person(){ return new Person("MrChengs",20); } }
@ComponentScan:
value :指定需要扫描的包
excludeFilters :指定扫描的适合排除那些包
Filter[] excludeFilters() default {};
FilterType type() default FilterType.ANNOTATION;
Class<?>[] classes() default {};
includeFilters: 指定扫描的时候只包含那些包
在使用的时候需要添加:useDefaultFilters=false属性
其余属性和excludeFilters类似
@Test public void test(){ ApplicationContext app = new AnnotationConfigApplicationContext(Config.class); //获取bean的name
String [] names = app.getBeanDefinitionNames(); for(String name : names){ System.out.println(name); } }
config
customerConteoller
customerService
per
关于@Filter的使用:
1.type=FilterType.ANNOTATION: 是根据注解的规则 2.type=FilterType.ASSIGNABLE_TYPE:按照给定的类型 @Filter(type=FilterType.ASSIGNABLE_TYPE,classes=CustomerService.class 3.type=FilterType.ASPECTJ:使用aspectj表达式 4.type=FilterType.REGEX:使用正则表达式 5.type=FilterTyoe.CUSTOM:自定义规则
使用5进行测试:
@ComponentScan(value="coom.MrChengs.config",includeFilters={ @Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class}), },useDefaultFilters=false)
public class MyTypeFilter implements TypeFilter{ //MetadataReader:读取到当前正在扫描的包信息 //MetadataReaderFactory:可以获取到其他类的任何信息 public boolean match(MetadataReader arg0, MetadataReaderFactory arg1) throws IOException { //获取当前类的注解信息 AnnotationMetadata annotationMetadata =arg0.getAnnotationMetadata(); //获取当前正在扫描类的信息 ClassMetadata classMetadata = arg0.getClassMetadata(); //获取当前类的资源(路径,url...) Resource resource = arg0.getResource(); //获取类的全类名 //扫描到的类 String className = classMetadata.getClassName(); System.out.println("--->" + className); return false; } }
在测试打印的时候
这些都是className中打印出来的
扫描到的类
--->coom.MrChengs.config.conteoller.CustomerConteoller --->coom.MrChengs.config.dao.CustomerDao --->coom.MrChengs.config.MyTypeFilter --->coom.MrChengs.config.service.CustomerService
当return true的时候
当然我们可以进行系统的判断进行放行
config
customerConteoller
customerDao
myTypeFilter
customerService
可以把所有的@ComponentScan都写在里面
@ComponentScans(value={@ComponentScan(value="coom.MrChengs.config",excludeFilters={ @Filter(type=FilterType.ANNOTATION,classes={Repository.class})})} )
4.@Scope 调整作用域
Config2.java
@Configuration public class Config2 { @Bean("per") public Person person(){ return new Person("MrChengs",20); } }
测试
@Test public void test2(){ ApplicationContext app = new AnnotationConfigApplicationContext(Config2.class); String [] names = app.getBeanDefinitionNames(); for(String name : names){ System.out.println(name); } Person p = (Person) app.getBean("per"); Person p1 = (Person) app.getBean("per"); System.out.println(p == p1); }
config2 per true
说明默认是单实例的,只实例化一个bean
@Scope
* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE * @see ConfigurableBeanFactory#SCOPE_SINGLETON * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
//prototype 多实例的 在IOC容器创建之后获取对象才开始创建,获取一次创建一次
//singleton 单例的 IOC容器启动的时候就会调用对象放到IOC容器中,多次获取也是只获取同一个
//request 同一次请求
//session 同一个session
@Configuration public class Config2 { //prototype 多实例的 //singleton 单例的 //request //session @Scope(value="prototype") @Bean("per") public Person person(){ return new Person("MrChengs",20); } }
config2 per false
多实例情况下,获取一次则创建一个实例