欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring框架的使用

程序员文章站 2023-10-21 19:46:37
第一章:Spring概述1. Spring全家桶:Spring、Spring MVC、Spring Boot、Spring Cloud2. Spring:出现在2002年左右,解决企业开发的难度,减轻对模块之间的管理,类和类之间的关系Spring核心技术ioc,aop。能实现模块之间、类之间的解耦合3. 依赖:类A中使用类B的属性或者方法,叫做类A依赖类B4. 特点1)轻量2)针对接口编程,解耦合3)AOP编程的支持4)方便集成各种优秀框架5. 框架怎么学?框架是一个软件,其他人...

第一章:Spring概述

1. Spring全家桶:

Spring、Spring MVC、Spring Boot、Spring Cloud

2. Spring:

出现在2002年左右,解决企业开发的难度,减轻对模块之间的管理,类和类之间的关系

Spring核心技术ioc,aop。能实现模块之间、类之间的解耦合

3. 依赖:

类A中使用类B的属性或者方法,叫做类A依赖类B

4. 特点

1)轻量

2)针对接口编程,解耦合

3)AOP编程的支持

4)方便集成各种优秀框架

5. 框架怎么学?

框架是一个软件,其他人写好的软件

1)知道框架能做什么,Mybatis——访问数据库,对表中的数据进行增删改查

2)框架的语法,框架要完成一个功能,需要一定步骤支持的

3)框架的内部实现,框架内部怎么做,原理是什么

4)通过学习,可以实现一个框架

第二章:IoC控制反转

1. IoC:

IoC(Inversion of Control):控制反转 是一个理论,概念,思想

描述的是:对象的创建,赋值,管理工作都交给代码之外的容器实现,也就是对象的创建是有其他外部资源完成

控制: 创建对象,对象的属性赋值,对象之间的关系管理

反转: 把原来开发人员管理,创建对象的权限转移给代码之外的容器实现。由容器 代替开发人员管理,创建对象

正转: 由开发人员在代码中,使用new构造方法创建对象(new对象这种行为叫做正转),开发人员主动的能够管理对象

容器: 是一个服务器软件,一个框架(Spring)

2. 为什么使用IoC ?

目的就是减少对代码的改动,也能实现不同的功能,实现解耦合

3. Java中创建对象的方式:

1)构造方法 new Student()

2)通过反射机制

3)序列化

4)克隆

5)IoC容器创建对象

6)动态代理

4. Spring实现步骤:

1.创建maven项目

2. 加入maven的依赖

spring依赖:

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>

maven编译Java程序插件:

<plugins>
  <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
      <source>1.8</source>
      <target>1.8</target>
    </configuration>
  </plugin>
</plugins>

3.创建类(创建接口和实现类)

接口:

package com.bjpowernode.service;

public interface SomeService {
    void doSome();
}

实现类:

package com.bjpowernode.impl;

import com.bjpowernode.service.SomeService;

public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome() {
        System.out.println("执行了SomeServiceImpl的doSome()方法");
    }
}

传统的执行SomeServiceImpl的doSome()方法:

package com.bjpowernode;

import com.bjpowernode.impl.SomeServiceImpl;
import com.bjpowernode.service.SomeService;
import org.junit.Test;

public class MyTest {
    @Test
    public void test01(){
        SomeService someService = new SomeServiceImpl();
        someService.doSome();
    }
}

4.创建Spring需要使用的配置文件

<?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="someService" class="com.bjpowernode.impl.SomeServiceImpl"/>
</beans>

1)声明bean,就是告诉spring要创建某个类的对象,一个bean标签声明一个对象。可以有多个bean标签

2)

id: 对象的自定义名称,唯一值/spring通过这个名称找到对象

相当于spring完成SomeService someservice = new SomeServiceIml;

class: 类的全限定名称(不能是接口,因为spring反射机制创建对象,必须使用类)

3)

spring是把创建好的对象放入到map中,spring框架有一个map存放对象的
springMap.put(id的值,对象);
例如:spring.put(someService,new SomeServiceImpl());

5.测试

测试调用doSome()方法:

public void test02(){
    //1.指定spring配置文件的名称
    String config = "beans.xml";
    //2.创建表示spring容器的对象,ApplicationContext
    //ApplicationContext就是表示spring容器,通过这个容器获取对象
    //ClassPathXmlApplicationContext从类路径中加载spring的配置文件
    //这里创建了someService对象,可以写个无参构造测试
    ApplicationContext ac = new ClassPathXmlApplicationContext(config);
    //从容器中获取某个对象,你要调用对象的方法
    SomeService someService= (SomeService) ac.getBean("someService");
    someService.doSome();
}

Spring默认创建对象的时间:在创建Spring容器时,会创建配置文件中的所有的对象,一个bean标签是一个对象

查看容器中定义对象的数量: int num = ac.getBeanDefinitionCount();

查看容器中每个定义对象的名称: String[] names = ac.getBeanDefinitionNames();

5. 给对象的属性赋值:

di: 依赖注入,表示创建对象,给属性赋值

di的实现方式有两种:

1.在spring文件中,使用标签和属性完成,叫做基于XML的di实现

2.使用spring中的注解,完成属性赋值,叫做基于注解的di实现

di的语法分类:

1.set注入(设值注入):spring调用类的set方法,在set方法可以实现属性的赋值

2.构造注入,spring调用类的有参数构造方法,创建对象,在构造方法中完成赋值

1.设值注入

<?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="student" class="com.bjpowernode.ba01.Student">
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
    </bean>
</beans>

property标签中的name属性:调用的是name属性对应的Set方法

因为只是使用set方法,所以类中即使没有email这个属性,只定义一个setEmail()方法也是可以正常执行的

当类中有引用类型的属性时呢?

Student类:

package com.bjpowernode.ba01;

public class Student {
    private String name;
    private int age;
    private School school;
    //Setter()方法.....
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

School类:

package com.bjpowernode.ba01;

public class School {
    private String name;
    private String address;
    //Setter()方法...
    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

XML文件中:

<?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="student" class="com.bjpowernode.ba01.Student">
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
        <property name="school" ref="MySchool"/>
    </bean>

    <bean id="MySchool" class="com.bjpowernode.ba01.School">
        <property name="name" value="北京大学"/>
        <property name="address" value="北京"/>
    </bean>
</beans>

2.构造注入

构造注入使用constructor-arg 标签

创建Student和School类,并加入构造方法:

package com.bjpowernode.ba01;

public class Student {
    private String name;
    private int age;
    private School school;

    public Student(String myname, int myage, School myschool) {
        this.name = myname;
        this.age = myage;
        this.school = myschool;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

//=======================================================
package com.bjpowernode.ba01;

public class School {
    private String name;
    private String address;

    public School(String schoolname, String schooladdress) {
        this.name = schoolname;
        this.address = schooladdress;
    }
    
    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

创建XML文件:

<?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="student" class="com.bjpowernode.ba01.Student">
        <constructor-arg name="myname" value="张三"/>
        <constructor-arg name="myage" value="20"/>
        <constructor-arg name="myschool" ref="MySchool"/>
    </bean>

    <bean id="MySchool" class="com.bjpowernode.ba01.School">
        <!--<property name="name" value="北京大学"/>
        <property name="address" value="北京"/>-->
        <constructor-arg name="schooladdress" value="北京"/>
        <constructor-arg name="schoolname" value="北京大学"/>
    </bean>
</beans>

也可以使用constructor-arg 标签的index属性,index可省略:

<bean id="student" class="com.bjpowernode.ba01.Student">
    <constructor-arg index="0" value="张三"/>
    <constructor-arg index="1" value="20"/>
    <constructor-arg index="2" ref="MySchool"/>
</bean>

创建测试类:

public class MyTest {
    @Test
    public void test01(){
        String config = "ba01/applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        Student student = (Student) ac.getBean("student");
        System.out.println(student);
    }
}

Student{name=‘张三’, age=20, school=School{name=‘北京大学’, address=‘北京’}}

一个constructor-arg标签表示构造方法的一个参数

constructor-arg标签中的属性:

name: 表示构造方法的形参名

index: 表示构造方法的参数的位置,参数从左往右的位置是从0开始的

value: 构造方法的形参类型是简单类型的,使用value

ref: 构造方法的形参类型是引用类型的,使用ref

3. 自动注入:

引用类型的自动注入:spring框架中根据某些规则可以给引用类型赋值,不用你再给引用类型赋值了

引用规则常用的是byName,ByType

byName:

按名称注入:Java类中引用类型的属性名和spring框架中(配置文件)bean标签的id名称一样,且数据类型是一致的,这样的容器中的bean,spring能够赋值给引用类型

1)创建Student类和School类

package com.bjpowernode.ba01;

public class Student {
    private String name;
    private int age;
    private School school;

	//setter方法...
    
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}
package com.bjpowernode.ba01;

public class School {
    private String name;
    private String address;

	//setter方法...
    
    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

2)XML文件:

<?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="student" class="com.bjpowernode.ba01.Student" autowire="byName">
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
    </bean>

    <bean id="school" class="com.bjpowernode.ba01.School">
        <property name="address" value="北京"/>
        <property name="name" value="北京大学"/>
    </bean>
</beans>

3) 测试类:

public class MyTest {
    @Test
    public void test01(){
        String config = "ba01/applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        Student student = (Student) ac.getBean("student");
        System.out.println(student);
    }
}

Student{name=‘张三’, age=20, school=School{name=‘北京大学’, address=‘北京’}}

byType:

按类型注入:Java类中引用的数据类型和spring容器中(配置文件)bean标签中的class属性是 同源 关系的,这样的bean能够赋值给引用类型

同源: 就是一类的意思

1)Java类中引用类型的数据类型和bean的class的值是一样的

2)Java类中引用类型的数据类型和bean的class的值是父子类关系的

3)Java类中引用类型的数据类型和bean的class的值是接口和实现类关系的

在上述byName代码的基础之上:

<?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="student" class="com.bjpowernode.ba01.Student" autowire="byType">
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
    </bean>

    <bean id="mySchool" class="com.bjpowernode.ba01.School">
        <property name="address" value="北京"/>
        <property name="name" value="北京大学"/>
    </bean>
    //假设MySchool这个类继承了School,且使用byType时,那么加入下面的bean标签会报错
    <bean id="mySchool" class="com.bjpowernode.ba01.MySchool">
        <property name="address" value="北京"/>
        <property name="name" value="北京大学"/>
    </bean>
</beans>

注意:自动类型注入xml中只能声明一个符合条件的,多于一个会报错

6. 为什么使用多配置文件:

当项目中的类很多,模块很多的时候,使用一个配置文件属实不方便

我们可以使用多配置文件来划分模块类型或类:

例如:项目中有 学生模块学校模块

学生模块:Spring-Student.xml

学校模块:Spring-School.xml

还需创建一个主配置文件:Total.xml

在Total.xml中写入import标签,并在import标签的resource属性中说明要链接的其他模块xml文件的位置

<?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">

    <import resource="classpath:ba01/Spring-Student.xml"/>
    <import resource="classpath:ba01/Spring-School.xml"/>
    
</beans>

也可以使用通配符的方式:Spring-*.xml

<import resource="classpath:ba01/Spring-*.xml"/>

使用这种方式时,主配置文件名称不能以Spring开头命名,否则会死循环,递归

7.基于注解的注入方式:

需要学习的注解:

1)@Component

2)@Respotory:用在持久层上面,放在dao的实体类上面,表示创建dao对象,dao对象是能访问数据库的

3)@Service:用在业务层类的上面的,放在service的实现类上面,创建service对象,service对象是做业务处理,可以有事务功能的

4)@Controller:用在控制器上面,放在控制器(处理器)类的上面,创建控制对象的,控制器对象能接受用户提交的参数,显示请求的处理结果

以上的功能是一样的,都能创建对象,但是这三个注解还有额外的功能,给项目对象分层的

5)@Value

6)@Autowired

7)@Resource

使用步骤:

1)创建实体类,并加入注解:

Student类:

package com.bjpowernode.ba01;

import org.springframework.stereotype.Component;
//加入注解,并命名
@Component(value = "myStudent")
public class Student {
    private String name;
    private int age;

    //Setter和Getter方法...

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

@Component(value = “myStudent”)

这句话的意思等同于:

<bean id="myStudent" class="com.bjpowernode.ba01.Student"/>

如果不指定value属性值,则获取bean的时候使用spring默认设置的名称:类名(首字母需小写)

2)在配置文件中声明扫描器:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.bjpowernode.ba01"/>
    
</beans>

3)创建测试类:

public class MyTest {
    @Test
    public void test01(){
        String config = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        Student student = (Student) ac.getBean("myStudent");
        System.out.println(student);
    }
}

如何在扫描器中指定多个不同的包呢?

指定多个包的三种方式:

1)使用多次的组件扫描器,指定不同的包

<context:component-scan base-package="com.bjpowernode.ba01"/>
<context:component-scan base-package="com.bjpowernode.ba02"/>
<context:component-scan base-package="com.bjpowernode.ba03"/>

2)使用分隔符(;或,)分隔多个包名

<context:component-scan base-package="com.bjpowernode.ba01;
                                      com.bjpowernode.ba02;
                                      com.bjpowernode.ba03"/>

3)指定父包

<context:component-scan base-package="com.bjpowernode"/>

简单类型的属性赋值:

使用@Value

value属性:

String类型的,表示简单类型的属性值

value属性可省略

位置:

1.在属性定义的上面

package com.bjpowernode.ba01;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("myStudent")
public class Student {
    @Value(value = "张三")
    private String name;
    @Value("25")
    private int age;

    
    public void setName(String name) {
        this.name = name;
    }
    
    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

2.在set方法的上面

package com.bjpowernode.ba01;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value = "myStudent")
public class Student {
    private String name;
    private int age;

    @Value(value = "张三")
    public void setName(String name) {
        this.name = name;
    }
    @Value(value = "25")
    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

引用属性的赋值:

使用@Autowired

有两种方式:byType和byName

位置:

1.在属性定义的上面

2.在set方法的上面

1.使用byType(默认就是byType)

1.创建School类并赋值:

package com.bjpowernode.ba01;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value = "mySchool")
public class School {
    @Value("北京大学")
    private String name;
    @Value("北京")
    private String address;

    public void setName(String name) {
        this.name = name;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

2.创建Student类并且给引用类型赋值:

package com.bjpowernode.ba01;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("myStudent")
public class Student {
    @Value(value = "张三")
    private String name;
    @Value("25")
    private int age;
    @Autowired
    private School school;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setSchool(School school) {
        this.school = school;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

3.创建测试类:

public class MyTest {
    @Test
    public void test01(){
        String config = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        Student student = (Student) ac.getBean("myStudent");
        System.out.println(student);
    }
}

Student{name=‘张三’, age=25, school=School{name=‘北京大学’, address=‘北京’}}

2. 使用使用byName

需要做的是:

1.在属性上面加入@Autowired

2.在属性上面加入@Qualifier(value = “bean的id”)

实现步骤:

1):创建School类:

package com.bjpowernode.ba01;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value = "mySchool")
public class School {
    @Value("北京大学")
    private String name;
    @Value("北京")
    private String address;

    public void setName(String name) {
        this.name = name;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

2)创建Student类:使用 @Qualifier(value = “mySchool”)

package com.bjpowernode.ba01;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("myStudent")
public class Student {
    @Value(value = "张三")
    private String name;
    @Value("25")
    private int age;
    @Autowired
    @Qualifier(value = "mySchool")
    private School school;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setSchool(School school) {
        this.school = school;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

3)创建测试类:

public class MyTest {
    @Test
    public void test01(){
        String config = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        Student student = (Student) ac.getBean("myStudent");
        System.out.println(student);
    }
}

Student{name=‘张三’, age=25, school=School{name=‘北京大学’, address=‘北京’}}

@Autowired的required属性

在上述使用byType给引用属性赋值的代码基础上:

如果**@Qualifier(value = “指定的bean的ID不存在”)** 的话,程序会报错并且停止运行,也就是下面的情况

   @Autowired
   @Qualifier(value = "我不存在哦!")
   private School school;

如何解决保存程序会执行结束的问题呢?

使用@Autowired的required属性:

默认和不写为true,表示引用类型赋值失败,程序报错并且终止运行

将其设置为false后,引用类型如果赋值失败,程序正常执行,引用类型的值为null

那么Autowired的required属性用true还是false呢?

使用true:能将问题爆露出来并能够及时得到解决

8.使用JDK中的注解给引用类型的属性赋值:

@Resource:来自jdk中的注解,spring框架中提供了对这个注解功能的支持,可以使用它给引用类型赋值

使用的也是自动注入原理,支持byName,byType,默认是byName

位置:

1.在属性的定义的上面,无需set方法,推荐使用

2.在set方法的上面

使用@Resource注解的,默认是Byname,如果byName找不到需要的bean,则自动使用byType

School类:

package com.bjpowernode.ba01;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value = "mySchool")
public class School {
    @Value("北京大学")
    private String name;
    @Value("北京")
    private String address;

    public void setName(String name) {
        this.name = name;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

Student类:

package com.bjpowernode.ba01;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component("myStudent")
public class Student {
    @Value(value = "张三")
    private String name;
    @Value("25")
    private int age;
    @Resource
    private School school;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setSchool(School school) {
        this.school = school;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

测试类:

package com.bjpowernode;

import com.bjpowernode.ba01.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    @Test
    public void test01(){
        String config = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        Student student = (Student) ac.getBean("myStudent");
        System.out.println(student);
    }

}

结果仍会正常执行并赋值,因为使用@Resource注解的,默认是Byname,如果byName找不到需要的bean,则自动使用byType

如果只想使用byName方式:

@Resource(name = "mySchool")
private School school;

9.XML和注解的方式怎么选择呢?

注解的缺点:

1、很多朋友比如在使用spring注解时,会发现注解分散到很多类中,不好管理和维护;这个其实要借助工具,我目前使用的是IDEA,它在这方面表现的非常好;当然现在还有Spring的STS,也是不错的; 所以借助工具,能解决这个问题;

2、注解的开启/关闭必须修改源代码,因为注解是源代码绑定的,如果要修改,需要改源码,这个有这个问题,所以如果是这种情况,还是使用XML配置方式;比如数据源;

3、注解还一个缺点就是灵活性,在实现复杂的逻辑上,没有XML来的更加强大;注解就是要么用,要么不用,比如之前的jpa bean validation,要么全,要么没;遇到这种情况很痛苦;

4、还一种就是约定大于配置,但是在处理一些复杂的情况下,注解还是需要的(如Spring的数据验证/数据绑定注解很强大);

5、通用配置还是走XML吧,比如事务配置,比如数据库连接池等等,即通用的配置集中化,而不是分散化,如很多人使用@Transactional来配置事务,在很多情况下这是一种太分散化的配置;

6、XML方式比注解的可扩展性和复杂性维护上好的多,比如需要哪些组件,不需要哪些;在面对这种情况,注解扫描机制比较逊色,因为规则很难去写或根本不可能写出来;

注解的好处:

1、XML配置起来有时候冗长,此时注解可能是更好的选择,如jpa的实体映射;注解在处理一些不变的元数据时有时候比XML方便的多,比如springmvc的数据绑定,如果用xml写的代码会多的多;

2、注解最大的好处就是简化了XML配置;其实大部分注解一定确定后很少会改变,所以在一些中小项目中使用注解反而提供了开发效率,所以没必要一头走到黑;

3、注解相对于XML的另一个好处是类型安全的,XML只能在运行期才能发现问题。

10. 读取配置文件:

1)首先在resorurce文件夹下创建配置文件:

test.properties

myname=张三
myage=20
myschool=北京大学
myaddress=北京

2)在spring的主配置文件中加入context:property-placeholder标签:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.bjpowernode.ba01"/>
    <context:property-placeholder location="classpath:test.properties"/>
</beans>

3)在Student类和School类中使用:

//Student类
package com.bjpowernode.ba01;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component("myStudent")
public class Student {
    @Value(value = "${myname}")
    private String name;
    @Value("${myage}")
    private int age;
    @Resource(name = "mySchool")
    private School school;


    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}
//School类
package com.bjpowernode.ba01;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value = "mySchool")
public class School {
    @Value("${myschool}")
    private String name;
    @Value("${myaddress}")
    private String address;

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

4)测试类:

package com.bjpowernode;

import com.bjpowernode.ba01.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    @Test
    public void test01(){
        String config = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        Student student = (Student) ac.getBean("myStudent");
        System.out.println(student);
    }
}

程序正常输出结果:

Student{name=‘张三’, age=25, school=School{name=‘北京大学’, address=‘北京’}}

第三章:AOP面向切面编程

本文地址:https://blog.csdn.net/qq_41151938/article/details/107068172