什么是bean

  • 基本属性有id和class
    • ID为bean在spring容器中的唯一标识
    • class为bean的全限定名称,即类的路径
    • spring读取配置文件,通过反射来创建bean
  • 默认情况下spring调用类中的无参构造函数来创建bean,如果没有无参构造函数则不能创建成功。所以如果定义了有参构造一定要把无参构造也定义上
  • 配置中Bean的顺序不重要,Spring根据依赖关系会自动正确初始化。

    项目结构

    image.png

  • 注意pom.xml与src一样是最高级

  • xml文件必须写在resource下才能被识别到
  • 类必须写java下才能被识别到。在spring看来java就是类的根目录

  • 注解版中配置类必须在自定义包最顶层

    XML配置

    导入Spring依赖

  • 实现Spring基本功能ioc,只需导入spring-context即可。spring-webmvc则包含了所有web开发需要的包,包括context

    1. <dependency>
    2. <groupId>org.springframework</groupId>
    3. <artifactId>spring-webmvc</artifactId>
    4. <version>5.1.10.RELEASE</version>
    5. </dependency>

    创建类

    public class Hello {
    private String name;
    public String getName() {
       return name;
    }
    public void setName(String name) {
       this.name = name;
    }
    public void show(){
       System.out.println("Hello,"+ name );
    }
    }
    

    装配/注入bean

    装配与注入是一回事

  • bean就是java对象 , 由Spring创建和管理,此即装配。

  • id为对象名,class为对象类型。每个类的id必须是唯一的!

    <?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 id="hello" class="com.kuang.pojo.Hello">   //必须在src/main/java下的包中才能识别到,所以一定要创建包
         <property name="name" value="Spring"/>
     </bean>
    </beans>
    
  • xml中不像java这么容易识别类型,所以类型/文件必须写完整路径

    获取bean以使用

  • ApplicationContext它就是一个ioc容器,可以实现装配,创建,获取bean

  • BeanFactory是另外一种ioc容器,BeanFactory的实现是按需创建,即第一次获取Bean时才创建这个Bean,而ApplicationContext会一次性创建所有的Bean。

    • 实际上,ApplicationContext接口是从BeanFactory接口继承而来的,并且,ApplicationContext提供了一些额外的功能,包括国际化支持、事件和通知机制等。通常情况下,我们总是使用ApplicationContext,很少会考虑使用BeanFactory。
      //解析beans.xml文件 , 生成管理相应的Bean对象.使用xml配置则调用ClassPath...方法
      ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
      //getBean : 获取bean对象。参数即为spring配置文件中bean的id .
      Hello hello = (Hello) context.getBean("hello");
      //bean对象的初始类型都是Object,必须强制转换为具体类型才能使用
      //这里除了可以强制转换,还可以通过反射进行转换   getBean("hello",Hello.class);
      hello.show();
      }
      
      BeanFactory factory = new XmlBeanFactory(new ClassPathResource("application.xml"));
      MailService mailService = factory.getBean(MailService.class);
      
  • hello 对象是由Spring创建的,对象的属性是由Spring容器设置的。

  • 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的,这个过程就叫控制反转 .我们要修改或者创建,直接改配置即可,不用再修改原代码了
  • 反转 : 程序本身不创建对象 , 而变成被动的接收对象 .
  • 依赖注入 : 就是利用set方法来进行注入的.

IOC是一种编程思想,由主动的编程变成被动的接

注解配置

  • @Compoent默认创建一个名称为类名小写的bean对象;也可以添加参数,创建指定名称的对象
    • 相当于<bean id="user" class="当前注解的类"/>
    • @Component("user001") 创建class为User类的叫user001的bean对象
  • @Value 注入值 只能用于原本可以property name="name" value="rao"/>进行注入的
    • 这里不写set和有参构造也能注入,不知道@Value怎么实现注入的
    • value注解只用于基本类和String类型的注入,除了自动装配还能直接设置值
  • @Autowired用于类类型的装配注入,不能设置值。相当于ref注入的xml。
    • 注意注入的bean要已经创建才能注入,创建使用@Component系列注解创建或者使用@Bean,@bean更灵活

  • @Configuration表示这是一个配置类
    • 标注了该注解的类就相当于是spring的启动类
    • 使用java类配置则使用AnnotationConfigApplicationContext来获取配置

  • @ComponentScan:指定扫描某个包下的注解,将这些注解交给ioc容器管理。
    • 不清楚无参数的该注解有什么作用
    • 等同于xml <context:component-scan base-package="..."/>
  • 关于getBean的具体使用方式见spring简介

    @Component
    public class User {
      public String getInfoUser() {
          return infoUser.a;
      }
    
      @Value("rao")
      private String name;
      private InfoUser infoUser;
    
      public String getName() {
          return name;
      }
    
      @Autowired
      public User(InfoUser infoUser) {
          this.infoUser = infoUser;
      }
    }
    
    @Component
    public class InfoUser {
      ...
    }
    
    //这里测试和
    @Configuration
    @ComponentScan
    public class Test {
      public static void main(String[] args) {
          ApplicationContext context = new  AnnotationConfigApplicationContext(Test.class);
          User user = context.getBean(User.class);
          System.out.println(user.getName());
      }
    }
    

    java配置

  • 注解配置是通过@Component及其延伸注解定义bean。java类配置则是通过@bean进行定义创建bean,无需@Component及其衍生注解。这是最本质的区别

    • java配置比较灵活(比如可以写些逻辑到@Bean方法里,不同情况返回不同实现bean),java配置中还可以使用注解配置的功能,如@Component等。
    • @Bean 注解是告诉 Spring 这是某个类的实例
  • 注解配置和java配置都需要用到@Configuration
    • 这个注解跟@Component作用差不多,不过还有个标注该类是注解类的作用(即仅仅是标明而已,实际作用跟component美色个么差别)
  • 测试时和注解配置一样,也是AnnotationConfigApplicationContext getBean
    • **AnnotationConfigApplicationContext**相当于ioc容器,它的作用是将java配置作为参数传入ioc容器中(交由ioc容器托管)
  • springboot的主程序也可以配置**bean**。因为主程序的@SpringBootApplication间接引用了@Configuration

    在注解配置的基础上增加@Bean方法,然后取消@Component即可,因为@Configuration包含了@Component注解
    @Configuration
    @ComponentScan
    public class Test {
    @Bean
    public User user(){
          return new User();
      }
      public static void main(String[] args) {
      //托管到ioc容器
          ApplicationContext context = new  AnnotationConfigApplicationContext(Test.class);
          //通过ioc容器获取bean
          User user = context.getBean(User.class);
          System.out.println(user.getName());
      }
    }
    

    三种配置总结:

  • spring最开始是使用xml,然后推出注解,最后推出java配置。现如今spring官方都推荐使用java类配置的方法

  • 三种方式其实就是通过不同方式获取到ApplicationContext,然后通过getBean(Class/bean名)获取bean

第一个Spring(IOC) - 图2

普通类获取spring的bean

  • 普通类即没有controller,service,component等注解标注的类。如一个普通的java工具类,在这些类里面使用autowired,resource等注入注解注入不进去,会报空指针异常。

    //对于非web项目可以这样:
    ApplicationContext ac =new File../Annotatiion/ClassPathXmlApplicationContext;
    ac.getBean("?")  //收入bean名或者路径
    比如
    ApplicationContext applicationContext=new AnnotationConfigApplicationContext(HelloController.class);
          HelloController helloController= (HelloController) applicationContext.getBean(HelloController.class);
    

    ```java //web应用上面这种方式不适合,相当于加载了两次 spring 容器。所以应当采用如下方式: //创建一个类并实现ApplicationContextAware,重写setApplicationContext。并托管该类到容器。该类提供外部方法供普通类获取ApplicationContext @Component public class SpringUtils implements ApplicationContextAware { private static ApplicationContext applicationContext;

    @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

      if (SpringUtils.applicationContext == null) {
          SpringUtils.applicationContext = applicationContext;
      }
    

    }

    public static ApplicationContext getApplicationContext() {

      return applicationContext;
    

    } }

//普通类使用时直接调用即可,托管类中既可以注入使用也可以直接调。

//如果是获取不到SpringUtils类的地方,则使用如下方法得到SpringUtils: @SpringBootApplication @ServletComponentScan @Import(value={SpringUtil.class}) public class App {

} ```