zoukankan      html  css  js  c++  java
  • SpringIOC容器底层注解使用

    w'wSpringIOC容器底层注解使用

    1. xml配置文件的形式VS配置类的形式

      1. 基于xml的形式定义bean的信息

        <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 定义一个 Bean 的信息 --> <bean id="car" class="com.demo.compent.Car"></bean> </beans>
        //去容器中读取bean
        public static void main( String[] args ) { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); System.out.println(ctx.getBean("person")); }
      2. 基于读取配置类的形式定义bean的信息

        @Configuration
        public class MainConfig{
           @Bean
           public Person person(){
               return new Person();
          }
        }
        //去容器中读取Bean的信息(传入配置类)
        public static void main(String[] args){
           AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext(MainConfig.class);
           System.out.println(ctx.getBean("person"));
        }
        //注意:通过@Bean的形式使用的话,bean的默认名称是方法名,若@Bean(Value="bean的名称"),那么bean的名称就是指定的
    2. 在配置类上写@ComponentScan注解来进行扫描

      @Configuration
      @ComponentScan(basePackage={"com.dome.testcompentscan"})
      public class MainConfig{

      }
    3. 排除用法excludeFilters:排除@Controller注解的和TestService的

      @Configuration
      @ComponentScan(basePackage={"com.demo.testcompentscan"})
      @ComponentScan.Filter(type=FilterType.ANNOTATION,value={Controller.class})
      @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,value={TestService.class})
      public class MainConfig{
         
      }
    4. 包含用法includeFilters:若使用包含的用法,需要把useDefaultFilters属性设置为false(true表示全部扫描)

      @Configuration
      @ComponentScan(basePackage={"com.demo.testcompentscan"},includeFilters={@ComponentScan.Filter(type=FilterType.ANNOTATION,value={Controller.class,Service.class})},userDefaultFilters=fasle)
      public class MainConfig{}
    5. 配置bean的作用域对象

      1. 在不指定@Scope的情况下,所有的bean都是单例的bean,而且是饿汉加载(容器启动实例就创建好了)

        @Bean
        public Person person(){
           return new Person();
        }
      2. 指定@Scope为prototype表示为多实例的,而且还是懒汉模式加载(IOC容器启动的时候,并不会创建对象,而是在第一次使用时才创建)

        @Bean
        @Scope(value="prototype")
        Public Person person(){
        	return new Person();
        }
      3. @Scope指定的作用域取值

        1. Singleton单例模式(默认)

        2. prototype多实例的

        3. request同一次请求

        4. session同一个会话级别

    6. Bean的懒加载@Lazy

      @Bean
      //主要针对单实例的bean的容器启动的时候,不创建对象,在第一次使用时才会创建该对象
      @Lazy
      public Person person(){
          return new Person
      }
    7. @Conditional进行条件判断等

      //场景:有两个组件TestAspect和TestLog,其中TestLog组件是依赖于TestAspect的组件
      //应用:自己创建一个TestCondition的类实现Condition接口
      public class TestCondition implements Condition{
          @Override
          public Boolean matches(ConditionContext context,AnnotatedTypeMetadata medata){
             // 判读容器中是否有TestAspect的组件
              if(context.getBeanFactory().containsBean("TestAspect")){
                  return ture;
              }
              return false;
          }
      }
      public class MainConfig{
         @Bean
         public TestAspect testAspect(){
             return new TestAspect();
        }
         //当且容器中有testAspect的组件,那么testLog才会被实例化
         @Bean
         @Condition(value=TestCondition.class)
         public TestLog testLog(){
             return new TestLog(;
        }
      }
    8. 往IOC容器中添加组件的方式

      1. 通过@CompentScan+@Controller@Service@Respository@Conpent

      2. 通过@Bean的方式来导入组件:适用于导入第三方组件的类

      3. 通过@Import来导入组件,导入 组件的id为类的全类名路径

        @Configuration
        @Import(value={Person.class,Car.class})
        public class MainConfig{}
        1. 通过@Import的ImportSelector类实现组件 的导入

          //导入组件的id为类的全路径
          public class TestImportSelector implements ImportSelector{
             //可以获取导入类的注解信息
             @Override
             public String[] selectImports(AnnotationMetadata importingClassMetadata){
                 return new String[]{"com.demo。testimport.compent.Dog"};
            }
          }
          @Configuration
          @Import(value={Person.class,Car.class,TestImportSelector.class})
          public class MainConfig{}
        2. 通过Import的ImportBeanDefinitionRegister导入组件

          //可以指定Bean的名称
          public class TestBeanDenifitionRegister implements ImportBeanDefinitionRegister{
             @Override
             public void registerBeanDefinitionRegister(AnnotationMetadata importingClassMetadata,BeanDenifitionRegistry registry){
                 //创建一个bean定义对象
                 RootBeanDefinition rootBeanDefinition=new RootBeanDefinition(Cat.class);
                 //把bean定义对象导入容器中
                 registry.registerBeanDefinition("Cat",rootBeanDefinition);
            }
          }
          @Configuration
          @Import(value={Person.class,Car.class,TestImportSelector.class,TestBeanDefinitionRegister.class})
          public class MainConfig{}
      4. 通过实现FactoryBean接口来实现注册组件

        public class CarFactoryBean implements FactoryBean<Car>{
           //返回Bean对象
           @Override
           public Car getObject() throws Exception{
               return new Car();
          }
           //返回bean的类型
           @Override
           public Class<?> getObjectType(){
               return Car.class;
          }
           //是否是单例模式
           @Override
           public Boolean isSingleton(){
               return true;
          }
        }
    9. Bean的初始化方法和销毁方法

      1. 什么是bean的生命周期

        bean的创建----->初始化----->销毁方法

        //有容器管理bean的生命周期,我们可以自己指定bean的初始化方法和销毁方法
        @Configuration
        public class MainConfig{
            //指定bean 生命周期的初始化方法和销毁方法
            @Bean(initMethod="init",destoryMethod="destory")
            public Car car{
                reutrn new Car();
            }
        }
        //针对于单实例bean的话,容器启动的时候,bean的对象就创建了,而且容器销毁的时候,也会调用bean的销毁方法 
        //针对多实例的bean的话,容器再启动的时候,Bean是不会被创建的,而且bean的销毁不受IOC容器的管理
      2. 通过InitalizingBean和DisposableBean的两个接口实现

        @Componment
        public class Person implements InitalizingBeab,DisposableBean{
           public Person(){
               System.out.println("Person的构造方法")
          }
           @Override
           public void destory() throws Exception{
               System.out.pringln(DisposableBean的destory()方法)
          }
           @Override
           public void afterPropertiesSet() throws Exception{
               System.out.rintln("InitialzingBean的afterPropertiesSet()方法")
          }
        }
      3. 通过Spring的BeanPostProcessor的bean的后置处理器会拦截所有bean的创建过程

        public class TestBeanPostProcessor implements BeanPostPrecessor{
           //在init方法调用之前
           @Override
           public Object postProcessBeforeInitialization(Object bean,String beanName) throws BeansException{
               System.out.pringln("TestBeanPostProcessor...postProcessBeaforeInitialization:"+beanName);
          }
           //在init方法调用之后
           @Override
           public Object postProcessAfterInitialization(Object bean,String beanName) throws BeansException{
               System.out.println("testBeanPostPrecessor...postProcessorAfterInitialization:"+beanName);
          }
        }
        //BeanPostProcessor的执行时间
        populateBean(beanName,mbd,instanceWrapper);
        initializeBeanBean{
           applyBeanPostProcessorBeforeInitialization();
        invokeInitMethods{
            isInitMethod{
                          isInitializingBean.afterPropertiesSet
        自定义的init方法
                   
            }
            applyBeanPostProcessorsAfterInitialization()方法
        }

        }
      4. 通过@Value+@PropertySource来给组件赋值

        public class Person{
           //通过普通的方式
           @Value("司马")
           private String firstName;
           //spel方式来赋值
           @Value("#{28-8}")
           private Integer age;
           //通过读取外配置文件的值
           @Value("${person.lastName}")
           private String lastName;
        }
        @Configuration
        //指定外部文件的位置
        @PropertySource(value={"classpath:person.properties"})
        public class MianConfig{
           @Bean
           public Person person(){
               return new Person();
          }
        }
    10. 自动装配

      1. @Autowired的使用

        1. 自动注入

          @Repository
          public class TestDao{}
          @Service
          public class TestService{
              @Autowired
              private TestDao testDao;
          }
        2. 自动注入结论

          1. 自动装配首先是按照类型进行装配,若在IOC容器中发现了多个相同类型的组件,那么就按照属性名称进行装配

            @AutoWired
            private TestDao testDao;
            //比如上面代码:如果容器中有两个TestDao类型的组件,一个叫做testDao,一个叫做testDao2,那么我们通过@Autowired来修饰的属性名称是testDao,那么就加载容器的testDao组件,如果属性名称是testDao2,那么容器就加载的是testDao2组件
          2. 假设需要指定特定的组件来进行装配,我们可以通过使用@Qualifier("testDao")来指定装配的组件,或者在配置类上的@Bean加上@Primary注解

            @Autowired
            @Qualifier("testDao")
            public TestDao testDao2;
            
          3. 假设容器中没有testDao也没有testDao2,那么在装配时就会抛出异常No qualifying bean of type'com.demo.testautowired.TestDao'available,若不想抛出异常,就需要指定required为false的时候就可以了

            @Autowired(required=false)
            @Qualifier("testDao")
            private TestDao testDao2;
          4. @Resource(JSR250规范):功能和Autowired差不多一样,但是不支持@Primary和@Qualifier的支持

          5. @Inject(JSR330规范):需要导入JAR包依赖。功能支持@Primary,但是没有Required=false的功能

            <dependency>
               <groupId>javax.inject</groupId>      <artifactId>javax.inject</artifactId>
            <version>1</version>
            </dependency>
            
            
          6. 使用Autowired可以标注在方法上

            1. 标注在set方法上

            2. 标注在构造方法上

            3. 标注在配置类的入参中

        3. 我们自己的组件如何使用SpringIOC底层组件

          //加入我们自己的组件组要使用ApplicationContext等,我们可以通过实现XXXAwire接口来实现
          @Component
          public class TestComponent implements ApplicationContextAware,BeanNameAware{
             private ApplicationContext applicationContext;
             @Override
             public void setBeanName(String name){
                 System.out.println("current beab name is:【"+name+"】")
            }
             @Override
             public void setApplicationContext(ApplicationContext applicationContext) throws BeansException{
                 this.applicationContext=applicationContext;
            }
          }
        4.  

         

       

       

       

       

  • 相关阅读:
    USACO 1.2 Broken Necklace
    USACO 1.2 Friday the Thirteenth
    USACO 1.1 Greedy Gift Givers
    USACO 1.1 Your Ride Is Here
    CSP考试策略
    CF444A DZY Loves Physics【结论】
    树状数组-复习笔记
    CF792E Colored Balls【思维】
    USACO4.4 Shuttle Puzzle【bfs+优化】
    拓扑排序-学习笔记
  • 原文地址:https://www.cnblogs.com/juddy/p/14395634.html
Copyright © 2011-2022 走看看