Spring注解版学习笔记——组件添加

 

 

1、AnnotationConfigApplicationContext

  使用AnnotationConfigApplicationContext 解析任何一个带有@ComponentScan(@ComponentScans) 的配置入口类,建立容器,注册bean,返回上下文。
  与之对应的是 ClassPathXmlApplicationContext,作用类似,不过解析的是入口xml文件
 
 1 public class MainTest {
 2     
 3     public static void main(String[] args) {
 4 //        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
 5 //        Person bean = (Person) applicationContext.getBean("person");
 6 //        System.out.println(bean);
 7         
 8         ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
 9         Person bean = applicationContext.getBean(Person.class);
10         System.out.println(bean);
11         
12         String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
13         for (String name : namesForType) {
14             System.out.println(name);
15         }
16     
17     }
18 
19 }
View Code

2、@ComponentScan(s)

  包扫描注解

 1 //配置类==配置文件
 2 @Configuration  //告诉Spring这是一个配置类
 3 
 4 @ComponentScans(
 5         value = {
 6                 @ComponentScan(value="com.atguigu",includeFilters = {
 7 /*                        @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
 8                         @Filter(type=FilterType.ASSIGNABLE_TYPE,classes={BookService.class}),*/
 9                         @Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class})
10                 },useDefaultFilters = false)    
11         }
12         )
13 //@ComponentScan  value:指定要扫描的包
14 //excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
15 //includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
16 //FilterType.ANNOTATION:按照注解
17 //FilterType.ASSIGNABLE_TYPE:按照给定的类型;
18 //FilterType.ASPECTJ:使用ASPECTJ表达式
19 //FilterType.REGEX:使用正则指定
20 //FilterType.CUSTOM:使用自定义规则
21 public class MainConfig {
22     
23     //给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
24     @Bean("person")
25     public Person person01(){
26         return new Person("lisi", 20);
27     }
28 
29 }
View Code

  重点关注自定义规则: FilterType.CUSTOM,对应的自定义规则类需要实现接口 TypeFilter ,Spring根据具体实现判断过滤规则

 1 public class MyTypeFilter implements TypeFilter {
 2 
 3     /**
 4      * metadataReader:读取到的当前正在扫描的类的信息
 5      * metadataReaderFactory:可以获取到其他任何类信息的
 6      */
 7     @Override
 8     public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
 9             throws IOException {
10         // TODO Auto-generated method stub
11         //获取当前类注解的信息
12         AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
13         //获取当前正在扫描的类的类信息
14         ClassMetadata classMetadata = metadataReader.getClassMetadata();
15         //获取当前类资源(类的路径)
16         Resource resource = metadataReader.getResource();
17         
18         String className = classMetadata.getClassName();
19         System.out.println("--->"+className);
20         if(className.contains("er")){
21             return true;
22         }
23         return false;
24     }
25 
26 }
View Code

  MetadataReader 类似于一个数据聚合期,同样可以类比到其他 xxxMetadata

1 public interface MetadataReader {
2     Resource getResource();
3 
4     ClassMetadata getClassMetadata();
5 
6     AnnotationMetadata getAnnotationMetadata();
7 }
View Code

3、@Bean

 1 @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
 2 @Retention(RetentionPolicy.RUNTIME)
 3 @Documented
 4 public @interface Bean {
 5     @AliasFor("name")
 6     String[] value() default {};
 7 
 8     @AliasFor("value")
 9     String[] name() default {};
10 
11     Autowire autowire() default Autowire.NO;
12 
13     String initMethod() default "";
14 
15     String destroyMethod() default "(inferred)";
16 }
View Code

  initMethod、destroyMethod 指定对应的初始化,销毁方法。与之对应的JSR250标准是:@PostConstruct,@PreDestroy

 1 @Component
 2 public class Dog implements ApplicationContextAware {
 3     
 4     //@Autowired
 5     private ApplicationContext applicationContext;
 6     
 7     public Dog(){
 8         System.out.println("dog constructor...");
 9     }
10     
11     //对象创建并赋值之后调用
12     @PostConstruct
13     public void init(){
14         System.out.println("Dog....@PostConstruct...");
15     }
16     
17     //容器移除对象之前
18     @PreDestroy
19     public void detory(){
20         System.out.println("Dog....@PreDestroy...");
21     }
22 
23     @Override
24     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
25         // TODO Auto-generated method stub
26         this.applicationContext = applicationContext;
27     }
28 
29 
30     
31 
32 }
View Code

4、@Configuration

  既有将自己的类加入容器,又可以在类中使用@Bean,添加其他的bean到容器中

5、@Component、@Service、@Controller、@Repository

6、@Conditional

  @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean。Condition为一个接口 

1 public interface Condition {
2     boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
3 }

  一个Condition实现类举例,判断是否为linux环境:

 1 //判断是否linux系统
 2 public class LinuxCondition implements Condition {
 3 
 4     /**
 5      * ConditionContext:判断条件能使用的上下文(环境)
 6      * AnnotatedTypeMetadata:注释信息
 7      */
 8     @Override
 9     public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
10         // TODO是否linux系统
11         //1、能获取到ioc使用的beanfactory
12         ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
13         //2、获取类加载器
14         ClassLoader classLoader = context.getClassLoader();
15         //3、获取当前环境信息
16         Environment environment = context.getEnvironment();
17         //4、获取到bean定义的注册类
18         BeanDefinitionRegistry registry = context.getRegistry();
19         
20         String property = environment.getProperty("os.name");
21         
22         //可以判断容器中的bean注册情况,也可以给容器中注册bean
23         boolean definition = registry.containsBeanDefinition("person");
24         if(property.contains("linux")){
25             return true;
26         }
27         
28         return false;
29     }
30 
31 }
View Code

7、@Primary

  @Primary:让Spring进行自动装配的时候,默认使用首选的bean;

8、@Lazy

  单实例bean:默认在容器启动的时候创建对象;懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化;
9、@Scope   作用域
  • prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象;
  • singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。以后每次获取就是直接从容器(map.get())中拿,
  • request:同一次请求创建一个实例
  • session:同一个session创建一个实例

10、@Import  快速给容器中导入组件

  • @Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
  • ImportSelector:返回需要导入的组件的全类名数组;
  • ImportBeanDefinitionRegistrar:手动注册bean到容器中
 1 //自定义逻辑返回需要导入的组件
 2 public class MyImportSelector implements ImportSelector {
 3 
 4     //返回值,就是到导入到容器中的组件全类名
 5     //AnnotationMetadata:当前标注@Import注解的类的所有注解信息
 6     @Override
 7     public String[] selectImports(AnnotationMetadata importingClassMetadata) {
 8         // TODO Auto-generated method stub
 9         //importingClassMetadata
10         //方法不要返回null值
11         return new String[]{"com.atguigu.bean.Blue","com.atguigu.bean.Yellow"};
12     }
13 
14 }
View Code
 1 public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
 2 
 3     /**
 4      * AnnotationMetadata:当前类的注解信息
 5      * BeanDefinitionRegistry:BeanDefinition注册类;
 6      *         把所有需要添加到容器中的bean;调用
 7      *         BeanDefinitionRegistry.registerBeanDefinition手工注册进来
 8      */
 9     @Override
10     public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
11         
12         boolean definition = registry.containsBeanDefinition("com.atguigu.bean.Red");
13         boolean definition2 = registry.containsBeanDefinition("com.atguigu.bean.Blue");
14         if(definition && definition2){
15             //指定Bean定义信息;(Bean的类型,Bean。。。)
16             RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
17             //注册一个Bean,指定bean名
18             registry.registerBeanDefinition("rainBow", beanDefinition);
19         }
20     }
21 
22 }
View Code

11、FactoryBean  工厂模式

  要点在于:(1)、实现接口 FactoryBean<T>

1 public interface FactoryBean<T> {
2     T getObject() throws Exception;
3 
4     Class<?> getObjectType();
5 
6     boolean isSingleton();
7 }

  (2)、ApplicationContext.getBean() 中传入 FactoryBean<T>的实现类(<? implements FactoryBean<T>>)得到的是 FactoryBean<T>.getObject()值。&beanName获取Factory本身

//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {

    //返回一个Color对象,这个对象会添加到容器中
    @Override
    public Color getObject() throws Exception {
        // TODO Auto-generated method stub
        System.out.println("ColorFactoryBean...getObject...");
        return new Color();
    }

    @Override
    public Class<?> getObjectType() {
        // TODO Auto-generated method stub
        return Color.class;
    }

    //是单例?
    //true:这个bean是单实例,在容器中保存一份
    //false:多实例,每次获取都会创建一个新的bean;
    @Override
    public boolean isSingleton() {
        // TODO Auto-generated method stub
        return false;
    }

}


public class IOCTest {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    
    
    @Test
    public void testImport(){
        printBeans(applicationContext);
        Blue bean = applicationContext.getBean(Blue.class);
        System.out.println(bean);
        
        //工厂Bean获取的是调用getObject创建的对象
        Object bean2 = applicationContext.getBean("colorFactoryBean"); // bean2为Color类型
        Object bean3 = applicationContext.getBean("colorFactoryBean");
        System.out.println("bean的类型:"+bean2.getClass());
        System.out.println(bean2 == bean3);
        
        Object bean4 = applicationContext.getBean("&colorFactoryBean"); //bean4为ColorFactoryBean 类型
        System.out.println(bean4.getClass());
    }
}

 

 

 

 

 

posted @ 2020-03-16 15:14  Demo12138  阅读(157)  评论(0编辑  收藏  举报