Spring源码笔记1

Spring源码笔记1

1、Spring框架功能整体介绍

在这里插入图片描述

1.1 Spring Core Container

  • Core和Beans模块是框架的基础部分,提供了IOC和DI的特性。这里的基础概念是BeanFactory,他提供对Factory模式的经典实现来实现程序“单例模式”的需要,并真正允许你从程序逻辑中分离出依赖关系和配置。
  • Context:处理BeanFactory,一般是用ApplicationContext。他构建与Core和Beans模块的基础之上。Context模块集成了Beans的特性,并未Spring核心提供了大量的扩展,添加了对国际化、事件传播、资源加载和对Context的透明创建的支持。也就是说,Context也是一个beanFactory,但是进行了功能的扩展。
  • BeanFactory和Application的本质区别是,BeanFactory是延迟加载的,ApplicationContext是非延迟加载的。BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化,ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化;
  • Expression Language:表达式语言,可以设置属性的值,一般用的比较少。

1.2 Spring Data Access/Integration(spring数据访问)

  • JDBC:JdbcTemplate,提供了一个JDBC的抽象层,可以消除冗长的JDBC编码。
  • ORM:流行的对象-关系映射:如JPA、JDO、Hibernate、iBatis等,提供一个交互层,利用ORM封装包。
  • OXM 模块提供了一个对 ObjecνXML 映射实现的抽象层,Object/XML 映射实现包括 JAXB、 Castor、 XMLBeans、 JiBX 和 XStrearn 。
  • Transaction支持编程和声明性的事务管理,这些事务类必须实现特定的接口,并且对所有的 POJO 都适用 。

1.3 SpringWeb

  • Web 模块:提供了基础的面向 Web 的集成特性c 例如,多文件上传、使用 servlet listeners 初始化 IoC 容器以及一个面向 Web 的应用上下文。 它还包含 Spring 远程支持中 Web 的相关部分。

1.4 Spring Aop

  • Aspects 模块提供了对 AspectJ 的集成支持。

2、Spring IOC容器底层的注解使用

2.1 把bean加入IOC容器,并获取

@Configuration
public class MainConfig {
    @Bean//默认是当实例的
    public TestHandler testHandler(){
        return new TestHandler();
    }
}

@Bean的形式注入,bean的默认名称是方法名,若是@Bean(value = “bean的名称”),那么bean的名称叫就是指定的。
去容器龚获得bean的信息:传入配置类

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
Object handler = context.getBean("testHandler");

2.2@CompentScan包扫描

@Configuration
@ComponentScan(basePackages = {"com.panzh.compentScan"});
public class MainConfig {
}

这里的basePackages是一个数组,也就是可以设置多个值,用大括号进行包裹
excludeFilters,过滤器用法:

@Configuration
@ComponentScan(basePackages = {"com.panzh.compentScan"},excludeFilters = {
        //过滤掉service注解的类,即该类不背扫描;
        @ComponentScan.Filter(type = FilterType.ANNOTATION,value = Service.class),
        //过滤掉特定了类,即可分配类型的
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = TestHandler.class)
})
public class MainConfig {
}

即可过滤掉我们需要过滤的类。
includeFilters的用法,若是使用这种方法,需要把useDefaultFilters设置为false,默认为true,表示扫描全部。

@Configuration
@ComponentScan(basePackages = {"com.panzh.compentScan"},includeFilters = {
        //过滤掉service注解的类,即该类不背扫描;
        @ComponentScan.Filter(type = FilterType.ANNOTATION,value = Service.class),
        //过滤掉特定了类,即可分配类型的
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = TestHandler.class)
},useDefaultFilters = false)
public class MainConfig {
}

@ComponentScan.Filter Type的类型

  • 注解形式:FilterType.ANNOTATION; @Controller、@Service。。
  • 指定类型:FilterType.ASSIGNABLE_TYPE; 我们特定的类
  • aspectj类型,不常用 FilterType.ASPECTJ
  • 正则表达式的类型 FilterType.REGEX(不常用)
  • 自定义类型 FilterType.CUSTOM;
public enum FilterType { 
    //注解形式  比如@Controller @Service @Repository  @Compent  
    ANNOTATION, 
    //指定的类型  
    ASSIGNABLE_TYPE, 
    //aspectJ形式的  
    ASPECTJ, 
    //正则表达式的  
    REGEX, 
    //自定义的  
    CUSTOM
 }

自定义Filter。我们需要写一个类集成TypeFilter,注意名称,不要写错了。
//自定义一个过滤器,也就是FilterType.CUSTOM

public class TulingFilterType implements TypeFilter {
    //方法返回true即加载到ioc容器,返回false则不包含到ioc容器;
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //获得类的元数据
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //也就定义了只有包含了“Handler”字符串的类可以被ico容器进行扫描;
        if (classMetadata.getClassName().contains("Handler")){
            return true;
        }
        return false;
    }
}

对每一个加入容器的主键进行过滤判断。启动的方式,跟上面几种类型是相同的。

3、Bean的作用域对象

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

 @Bean     
 public Person person() {
   return new Person();
}

使用@Scope属性可以设置作用域方法。如果Scope的属性为prototype,表示为多实例的,并且为懒汉加载模式((IOC容器启动的时候,并不会创建对象,而是 在第一次使用的时候才会创建)

 @Bean     
 @Scope(value = "prototype")     
 public Person person() {         
 return new Person();     
 } 
  • singleton:单实例(默认)
  • prototype:多实例,懒加载
  • request:同义词请求
  • session:同一个会话级别
    @bean的懒加载注解@Lazy(主要针对单实例的bean容器启动的时候,不创建对象,在第一次使用的时候创建对象)
 @Bean     
 @Lazy     
 public Person person() {
     return new Person();     
} 

@Conditional条件判断。如果返回true,表示条件成立,放入ioc容器,不成立就不放进ioc 容器。
我们自己写一个类实现Condition接口

public class TulingCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        if (conditionContext.getBeanFactory().containsBean("123")){
            return true;
        }
        return false;
    }
}
@Configuration
public class MainConfig {
    @Bean//默认是当实例的
    @Conditional(TulingCondition.class)//必须符合条件,才会被加载进ioc容器
    public Cat cat(){
        return new Cat();
    }
}

往IOC容器中添加组件的方法:

  • @CompentScan + @Controller @Service @Respository @compent
  • 通过@Bean的方式来导入组件(适用于第三方主键的类)
  • 通过@Import来导入组件(导入的主键的id为全类名路径)
@Configuration 
@Import(value = {Person.class, Car.class})
public class MainConfig { }
  • 通过Import的ImportSelector类实现主键的导入。
public class TulingImportSelector implements ImportSelector {
  //可以获取导入类的注解信息    
  @Override     
  public String[] selectImports(AnnotationMetadata importingClassMetadata) {
           return new String[]{"com.tuling.testimport.compent.Dog"};     
  } } 
@Configuration 
@Import(value = {Person.class, Car.class, TulingImportSelector.class})
public class MainConfig { }

通过@Import的 ImportBeanDefinitionRegister导入组件  (可以指定bean的名称),导入到bean定义的注册器。
public class TulingBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {     
@Override     
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
       //创建一个bean定义对象         
       RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Cat.class);         
       //把bean定义对象导入到容器中         
       registry.registerBeanDefinition("cat",rootBeanDefinition);
 } } 
@Configuration 
@Import(value = {Person.class, Car.class, TulingImportSelector.class, TulingBeanDefinitionRegister.class}) 
public class MainConfig {}

通过实现Factory接口来实现注册主键。

4、bean的生命周期

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

1. 由容器管理bean的生命周期,我们可以指定bean 的初始化方法和销毁方法

@Configuration public class MainConfig { 
   //指定了bean的生命周期的初始化方法和销毁方法. 
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car() {
       return new Car();
    }
}

针对单实例bean的话,容器启动的时候,bean的对象就创建了,而且容器销毁的时候,也会调用Bean的销毁方法
针对多实例bean的话,容器启动的时候,bean是不会被创建的而是在获取bean的时候被创建,而且bean的销毁不受 IOC容器的管理.

2. InitializingBean和DisposableBean 的二个接口实现bean的初始化以及销毁方法

@Component public class Person implements InitializingBean,DisposableBean { 
    public Person() {
        System.out.println("Person的构造方法");
    } 
    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean的destroy()方法 ");
    } 
    @Override     
    public void afterPropertiesSet() throws Exception {
       System.out.println("InitializingBean的 afterPropertiesSet方法");
    } 
}

③:通过JSR250规范 提供的注解@PostConstruct 和@ProDestory标注的方法

@Component public class Book { 
    public Book() {         
       System.out.println("book 的构造方法");
   } 
   //构造之后调用
    @PostConstruct     
    public void init() {
         System.out.println("book 的PostConstruct标志的方法");
     } 
     //销毁之前调用
    @PreDestroy
    public void destory() {
         System.out.println("book 的PreDestory标注的方法");
    }
}

4:通过Spring的BeanPostProcessor的 bean的后置处理器会拦截所有bean创建过程

postProcessBeforeInitialization 在init方法之前调用
postProcessAfterInitialization 在init方法之后调用

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

自动装配:先根据类型进行查找,如果有多个,就按照属性名称来查找。
可以添加注解,按照指定的名字进行查找

@Qualifier("tulingDao") //指定按照tulingDao的名称来进行查找

如果没有的话,我们的ioc容器会报错,我们为了不报错,可以加上这个注解:

@Autowired(required = false) 

另外@Autowired可以加在set方法上,表示到ioc容器中寻找合适的参数进行注入。亦可以标注在构造方法上,告诉ioc容器按照这个构造方法注入,如果只有一个构造方法,可以不标注。

当我们的组件需要使用到ioc底层的组件的时候,我们可以实现xxxAware接口来实现:

@Component public class TulingCompent implements ApplicationContextAware,BeanNameAware { 
    private ApplicationContext applicationContext; 
    @Override     
    public void setBeanName(String name) {         
        System.out.println("current bean name is :【"+name+"】");
     } 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
             this.applicationContext = applicationContext;
    } 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吴涛_1618

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值