Spring--01

IOC
  • 定义:
  IOC: inverse of controll   控制反转
  将对象的创建权交给Spring去管理
  • 如何将一个bean交给Spring去管理
  通过@Configuration@Bean注解来管理
@Configuration和@Bean注解
  • @Configuration
  用于定义在类的上方,表明该类为配置类,Spring框架启动时加载
  • Bean
  定义在方法的上方,表示该方法会返回一个Bean对象,每个Bean对象都会有自己的beanid
      - 若在配置类中通过@Bean注解的方式来定义bean对象,此时@Bean方法的方法名即为beanid
  • 应用:
  public class UserRepository{
   .....    
  }
  
  public class UserService{....}
  
  @Configuration
  public class MyConfig{
      @Bean
      public UserRepository userRepository(){
          return new UserRepository();
      }
      
      @Bean
      public UserService userService(UserRepository userRepository){
          
      }
      
  }
  
  注意点:@Bean作用的方法可以是无参的,可以是有参的,若有参,参数一定是Spring中的Bean对象,此时,会自动注入
  • 如何获取某个bean对象
  通过ApplicationContext(上下文对象)来获取某个bean对象
ApplicationContext对象
  上下文对象,(Spring容器),Spring会管理一系列的Bean对象,若想获取某个Bean对象,则需要从ApplicationContext对象中获取.
     
  使用场景:
  	  1. Junit单元测试环境下可以使用该对象
      2. Web应用程序环境
      3. 独立的应用程序
  注意点:ApplicationContext对象不论在哪种环境下使用,所有的bean实例均已实例化好
  • 从ApplicationContext对象中获取Bean对象
    //根据beanid获取Bean对象
    UserRepository userRepository = 
    	(UserRepository) applicationContext.getBean("userRepository");
    
    //根据beanid获取Bean对象,但是不需要强转
    UserRepository userRepository = 
    	applicationContext.getBean("userRepository",UserRepository.class);
    
     //根据类型获取Bean对象,适用于类型的实例只有一个时
    UserRepository userRepository = 
    	applicationContext.getBean(UserRepository.class);
Bean的作用域
Spring中所有的Bean默认的作用域是单例的
通过@Scope("val")的方式来设置bean的作用域
    eg:
	@Configuration
	public class MyConfig{
        @Bean
        @Scope("prototype")
        public T t(){
            return new T();
        }
    }
    
Bean的作用域:
	Singleton -- 单例
    prototype -- 原型
		-每次获取Bean对象,都会重新实例化一个新的Bean对象返回
    request  --仅限WEB环境
        -每次请求均会重新创建实例
    session  --仅限web环境,session的作用域是一次会话(从浏览器打开到浏览器关闭)
        -每创建一个session对象,会重新实例化

session的作用域是一次会话的原因:
	在服务器端创建session对象后,每个session对象都有唯一的sessionId,而sessionId会保存在cookie对象中,下发给浏览器,客户端向访问session对象中的数据,必须携带sessionId去服务器端找session对象;而cookie对象默认的age值为-1,即表示cookie是保存在浏览器内存中的,那么浏览器关闭,对应的cookie对象会销毁,即sessionId会销毁,再次打开浏览器,就没有办法访问到之前的session对象,而浏览器从打开到关闭是一次会话.所以session对象的作用域为一次会话.
    但是在服务器端session对象并不会立即销毁,而是从闲置开始的30min后自动销毁.
        
 cookie对象的方法: setMaxAge(int) --设置cookie对象的保存时长
     		参数:
				负数:都等同于-1,即cookie是保存在浏览器的内存的
                正数:表示cookie对象保存到磁盘多少分钟
                0:删除该cookie对象
配置好的Bean对象其实都可以看成是Spring的组件,所以Spring中配置Bean还可以使用组件隐式配置
Spring中提供了一系列组件类注解,在定义类的时候,在类上方添加上该注解后,即表示,这个类会成为Spring的组件,自动配置为Bean对象,无需后续再配置类中通过@Bean的方式来配置Bean对象
  • Bean配置的2种方式
  显示配置 -- @Bean
  隐式配置 -- 组件类注解
  • 组件类注解
  Spring框架提供的组件类注解
      @Component -- 通用组件
      @Controller -- 控制器组件
      @Service -- 业务层组件
      @Repository -- 持久层组件
  • Bean显示和隐式配置的使用场景
  若是自己写的类,则使用组件类注解
  若是将不是自己写的类定义成bean,必须在配置类中使用@Bean
      eg:
  		连接数据库需要一个对象  DataSource 
  • 组件的名称
  @Component
  public class UserService{
      
  }
  以上bean的beanid为:
  	若类名首字母大写,第二位是小写的,则beanid为类名首字母小写后的名称 -- userService
      若首字母大写,第二个也是大写的,此时beanid为类名 
          	eg:class USerService --beanid为USerService
  • 组件扫描
  Spring框架要想把添加了组件注解的类装配成Bean对象,必须扫描这些注解,此时就需要组件扫描注解
  注意:SpringBoot项目中,启动类的注解中已经包含了@ComponentScan,已经定义了扫描的包范围,所以在SpringBoot项目中我们无需再次使用该注解,但是若使用的是Spring项目,则必须添加该注解 
  @ComponentScan如何指定扫描的包范围
      @ComponentScan("cn.tedu.springtest")
      @ComponentScan({"cn.tedu.controller","cn.tedu.service"}) 
      	-- 数组的形式指定扫描的包
依赖注入
依赖注入DI(Denpendcy Injection),在某个bean中,若要使用其中的bean对象,通过注解直接注入该对象
  • 注入的注解

    • @Autowired - 根据数据类型注入,是Spring提供的注解
    1. 字段注入
        @Autowired
        UserRepository userRepository;
    2. 构造方法注入
       class T{
           @Autowired
           T(UserRepository userRepository){
           }
       }
    注意:
		1. 若类中只有一个构造方法,构造方法的参数列表中为Spring管理的bean对象,此时构造方法上方可以省略@Autowired注解,同样可以达到注入对象的效果
		2. 构造方法注入中,参数列表中可以注入多个bean对象
		3. setter注入  --- set方法注入
        在Spring容器启动时,会自动调用set方法进行注入,set方法的参数列表中可以有一个参数,可以有多个参数,使用@Autowired注解可以注入以上对象.
  • 自动布线和消除歧义
      自动布线:使用@Autowired注解时,我们叫做自动布线,即自动装配
         
      歧义的产生:当一个数据类型对应的bean实例超过一个时,此时会产生歧义
      消除歧义:前提:一个数据类型的bean实例超过一个
          1. 使用@Qualifier注解,指明注入的beanid,此时根据beanid进行注入
          	- @Autowired是根据数据类型进行注入的
          		-若不存在对应数据类型的Bean对象,则注入失败,编译不通过.
      			-若该类型的bean对象有多个,此时会根据beanid进行注入
          2. 若没有@Qualifier注解,此时会自动根据类型后的名称来进行beanid匹配,若存在对应的beanid,则注入成功;若不存在对应的beanid,注入失败
  • @Resource – 根据name/beanid进行注入的
    @Resource注解不是Spring框架提供的,而是java提供的,是根据bean的名称/beanid注入对象的.
    注入方式:首先默认根据beanid进行注入,若beanid不存在,则自动回退到根据数据类型进行注入
        -若该类型不存在,则抛出运行时异常
        -若该类型存在,且只有一个bean实例,注入成功
        -若该类型存在,但是有多个bean实例,此时注入失败,除非使用@Qualifier指定beanid
      
    @Resource注解可以指定name/beanid,若指定了name,此时只能根据name来注入,若不存在对应的name,则直接注入失败,不会回退到类型注入
        
    @Resource注解的注入方式:只适用于setter注入和字段注入
    ~~~

    - @Qualifier注解作用于构造方法和setter方法时的使用

      ~~~java
      该注解必须写在字段之上或之前,不可以写在方法上 
      @Autowired
      public void setUserService(@Qualifier("foo1") Foo foo){
  • 注入方式
  1. 构造方法注入
  2. Setter注入
  3. 字段注入(属性注入)
工厂模式 - 设计模式
Spring就是一个工厂,Bean的工厂
Spring中的配置类是工厂,在配置类中,添加了@Bean注解的方法就是工厂方法
Spring的工厂接口FactoryBean
需要了解FactoryBean接口中的方法getObject()的调用
在Spring早期是通过xml配置的方式来进行开发的,若要对Bean进行复杂初始化,没有直接的方法,需要实现FactoryBean接口,重写其中的抽象方法getObject().在该方法内存完成复杂初始化,Spring启动时会自动调用该方法,无需程序员调用.
还有重写getObjectType方法,返回bean的类型
该接口中还有一个方法isSingleton,返回当前实例是否为单例,Spring5版本开始默认为单例
Bean的生命周期 – 面试热点
1. 初始化
    1.加载bean
    2.进入后处理bean--将所有的bean交给BeanFactoryPostProcessor(BFPP)
    	- BFPP经常用于自定义作用域和引用配置文件中的属性值
 	3.查找/创建依赖
    4.实例化bean-->构造方法注入-->字段注入-->setter注入
    5.Bpp(BeanPostProcessor) - beforeInit
    6.调用初始化器 
    	-Spring提供了一个生命周期中的注解@PostConstruct(setter注入之后执行初始化)
    7.Bpp(BeanPostProcessor) - afterinit
2. 使用
    不论是通过context获取bean对象还是通过注入的方式来获取bean对象,若在初始化过程中使用了Bpp,则得到bean对象为代理对象(对原对象进行了加工,之后执行的都是加工后的代码,新对象就叫做代理对象)
    产生代理对象需要使用代理机制,SpringBean对象的创建会使用动态代理机制:
		-JDK动态代理:使用JDK提供的api方法来生成代理对象的,要求目标对象一定实现了接口
        -CGLIB动态代理:使用CGLib提供的api方法来生成代理对象的,要求目标对象没有实现接口
            
    动态:在运行期执行的操作,叫做动态,而在运行期执行操作是通过反射来完成的
3. 销毁
     在context对象关闭之前会销毁所有的bean对象,但是会先调用添加了@PreDestory注解的方法,然后才销毁bean实例
生命周期相关注解@PostConstruct和@PreDestory
以上两个注解均是用于添加在方法上方的
@PostContruct:表示方法在构造方法注入-->字段注入-->setter注入之后,执行该方法
@PreDestory:表示方法在bean销毁之前会被调用
    

注意点:
	1.以上2个注解使用的前提:方法必须没有参数,且方法的返回值必须为void
    2.以上2个注解是java提供的,而不是spring提供的
    3.仅当应用程序正常关闭时会调用PreDestroy方法,如果进程意外终止或强制终止则不会调用。
也可以使用一下的方案替换以上2个注解:
@Bean(initMethod="populateCache", destroyMethod="flushCache")
public AccountRepository accountRepository() {                                  
        // ...
}

使用场景:
	如果是自己的类,使用@PostConstruct/@PreDestroy
 	如果不是自己写的类,也无法添加注解,只能使用@Bean的属性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值