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

多实例情况下,获取一次则创建一个实例

 

posted @ 2018-12-12 15:21  MrChengs  阅读(535)  评论(0编辑  收藏  举报