Java(Spring01)

Java(Spring01)

参考视频:Spring5最新完整教程IDEA版通俗易懂(狂神)

1. Spring

1.1 简介

  • Spring:春天 -----> 给软件行业带来春天。
  • 2002,首次推出了Spring框架的雏形:interface21框架。
  • Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日,发布了1.0正式版。
  • Rod Johnson,Spring Framework创始人,著名作者。很难想象Rod Johnson的学历,真的让好多人大吃一惊,他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学
  • spring理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架!

  • SSH:Structs + Spring + Hibernate
  • SSM:SpringMVC + Spring + Mybatis

  • 官网:
    • https://spring.io/projects/spring-framework#learn
    • https://docs.spring.io/spring-framework/docs/current/reference/html/
  • 官方下载地址:
    • https://docs.spring.io/spring-framework/docs/4.3.9.RELEASE/spring-framework-reference/html/
    • 点击Distribution Zip Files
    • 点击http://repo.spring.io/release/org/springframework/spring
  • GitHub地址:
    • https://github.com/spring-projects/spring-framework
  • 中文文档:
    • https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/

  • maven依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>

1.2 优点

  • Spring是一个开源的免费的框架(容器)
  • Spring是一个轻量级的,非侵入式的框架
  • 控制反转(IOC),面向切面编程(AOP)
  • 支持事务的处理,对框架整合的支持

  • 总结:Spring是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架。

1.3 组成

在这里插入图片描述

1.4 拓展

  • 在Spring的官网有这个介绍:现代化的Java开发,说白了就是,基于Spring的开发!
    在这里插入图片描述
  • Spring Boot
    • 一个快速开发的脚手架。
    • 基于SpringBoot可以快速地开发单个微服务。
    • 约定大于配置。
  • Spring Cloud
    • SpringCloud是基于SpringBoot实现的。

  • 现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,必须要完全掌握Spring以及SpringMVC!承上启下的作用!

  • 弊端: 发展了太久之后,违背了最初的理念!配置十分繁琐,人称“配置地狱”。

2. IOC理论推导

  1. UserDao 接口
public interface UserDao {
    void getUser();
}
  1. UserDaoImpl 实现类
public class UserDaoImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("默认获取用户的数据");
    }
}
  1. UserService 业务接口
public interface UserService {
    void getUser();
}
  1. UserServiceImpl 业务实现类
  • 被用户控制
public class UserServiceImpl implements UserService{
    
    private UserDao userDao = new UserDaoOracleImpl();//随用户需求改动
    
    @Override
    public void getUser() {
        userDao.getUser();
    }
}
  • 控制反转
public class UserServiceImpl implements UserService{
    
    private UserDao userDao;
    
    //利用set进行动态实现值的注入!
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;//用户要什么自己挑了传过来就行
    }
    
    @Override
    public void getUser() {
        userDao.getUser();
    }
}

在这里插入图片描述

  • 在我们之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改原代码!如果程序代码量十分大,修改一次的成本代价十分昂贵!
  • 我们用一个Set接口实现。已经发生了革命性的变化!
  • UserServiceImpl
    private UserDao userDao;
    
    //利用set进行动态实现值的注入!
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
  • 之前,程序是主动创建对象!控制权在程序猿手上!
  • 使用了set注入后,程序不再具有主动性,而是变成了被动地接受对象!
  • 这种思想,从本质上解决了问题,我们程序猿不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专注在业务的实现上!这就是IOC的原型!
    在这里插入图片描述

IOC本质

  • 控制反转loC(Inversion of Control),是一种设计思想,Dl(依赖注入)是实现loC的一种方法,也有人认为DI只是loC的另一种说法。没有loC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
  • 采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
  • 控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是loC容器,其实现方法是依赖注入(Dependency Injection, DI)。

3. HelloSpring

  1. 先添加一个依赖
	<dependencies>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>5.2.0.RELEASE</version>
		</dependency>
	</dependencies>
  1. Hello实体类
  • 只有set、get方法(和一个toSting方法),没有有参构造方法!(但无参构造是默认存在的…)
package com.zach.pojo;

public class Hello {
    private String str;
    
    public String getStr() {
        return str;
    }
    
    public void setStr(String str) {
        this.str = str;
    }
    
    @Override
    public String toString() {
        return "Hello{" +
                "str='" + str + '\'' +
                '}';
    }
}
  1. 在resources中添加文件beans.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!--使用Spring来创建对象,在Spring中这些都成为Bean
	类型 变量名 = new 类型();
	Bean = 对象 new Hello();
	
	id = 变量名
	class = new的对象
	property相当于给对象中的属性设置一个值
	-->
	<bean id="hello" class="com.zach.pojo.Hello">
		<property name="str" value="Spring"/>
	</bean>

</beans>
  1. MyTest
import com.zach.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        // 获取Spring的上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        // 我们的对象现在都在Spring中管理了,我们要使用,直接去里面取出来就可以了。
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.toString());
    }
}
  • 思考问题:
    • Hello 对象是谁创建的 ?
      • hello 对象是由 Spring创建
    • Hello 对象的属性是怎么设置的 ?
      • hello 对象的属性是由 Spring容器 设置的

  • 这个过程就叫 控制反转:
    • 控制:谁在控制对象的创建,传统的应用程序的对象是由程序本身控制创建的,使用spring后, 对象由spring来创建
    • 反转:程序本身不创建对象,而变成被动地接收对象。
  • 依赖注入: 就是利用set方法来进行注入的.

  • IOC是一种编程思想,由主动地编程变成了被动地接收。
  • 尝试通过newClassPathXmlApplicationContext去浏览一下底层源码。(目前先不看了)

  • 修改一下上一个的Module:spring-01-ioc1
  • 在resources新增一个spring配置文件beans.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
	
		<bean id="mysqlImpl" class="com.zach.dao.UserDaoMysqlImpl"/>
		<bean id="oracleImpl" class="com.zach.dao.UserDaoOracleImpl"/>
		<bean id="sqlserverImpl" class="com.zach.dao.UserDaoSqlserverImpl"/>
		
		<bean id="UserServiceImpl" class="com.zach.service.UserServiceImpl">
			<!--ref:引入Spring容器中创建好的对象-->
			<!--value:具体的值,基本数据类型-->
			<property name="userDao" ref="sqlserverImpl"/>
		</bean>
	
</beans>
  • MyTest
import com.zach.dao.UserDaoImpl;
import com.zach.dao.UserDaoMysqlImpl;
import com.zach.dao.UserDaoOracleImpl;
import com.zach.dao.UserDaoSqlserverImpl;
import com.zach.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        //获取ApplicationContext:拿到Spring的容器
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        
        //容器在手,天下我有,需要什么,get什么!
        UserServiceImpl userService = (UserServiceImpl) context.getBean("UserServiceImpl");
        
        userService.getUser();
    }
}
  • 现如今,我们彻底不用再程序中去改动了,要实现不同的操作,只需要在xml配置文件中进行修改,所谓的loC,一句话搞定: 对象由Spring来创建,管理,装配!

4. IOC创建对象的方式

  1. 使用无参构造创建对象,默认!
package com.zach.pojo;

public class User {
    private String name;
    
    public User() {
        System.out.println("User的无参构造!");
    }//只留下有参构造,beans.xml的class会报错:No matching constructor found in class 'User'

    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public void show(){
        System.out.println("name = "+name);
    }
}
	<!--当使用默认的无参构造时-->
	<bean id="user" class="com.zach.pojo.User">
		<property name="name" value="张天道"/>
	</bean>
public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) context.getBean("user");
        user.show();
    
    }
}
  1. 假设我们要使用有参构造创建
  • 下标赋值
	<!--第一种:通过下标赋值 匹配-->
	<bean id="user" class="com.zach.pojo.User">
		<constructor-arg index="0" value="张酬勤"/>
	</bean>
  • 类型赋值
	<!--第二种:通过参数赋值 匹配。但不建议使用,通常由多个同类型参数...-->
	<bean id="user" class="com.zach.pojo.User">
		<constructor-arg type="java.lang.String" value="天道酬勤"/>
	</bean>
  • 参数名
	<!--第三种:直接通过参数名来设置-->
	<bean id="user" class="com.zach.pojo.User">
		<constructor-arg name="name" value="张天道&amp;张酬勤"/>
	</bean>
  • 总结:在配置文件加载的时候,容器中管理的对象就已经初始化了!

5. Spring配置

5.1 别名

	<!--别名:如果添加了别名,那我们同时也可以通过别名获取该对象了-->
	<alias name="userT" alias="userAlias"/>

5.2 Bean的配置

	<!--
	id:bean的唯一标识符,也就是相当于我们学的对象名
	class:bean对象所对应的全限定名:包名 + 类名
	name:也是别名,但name更高级,可以同时取多个别名,可以用多种符号分隔
	-->
	<bean id="userT" class="com.zach.pojo.UserT" name="userAliasAlso,userAliasToo userZaiXia;userZhang">
		<property name="name" value="在下张别名"/>
	</bean>

5.3 import

  • 这个import,一般在团队开发中使用,它可以将多个配置文件 导入 ,并且实现 合并 为一个。
  • 假设,目前项目中有多个人在开发,这三个人复制不同的开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml和合并为一个总的。
    • 张三的
    • 李四的
    • 王五的
    • applicationContext.xml(合并到此)
	<import resource="beans.xml"/>
	<import resource="beans2.xml"/>
	<import resource="beans3.xml"/>
  • 使用的时候,直接使用总的配置applicationContext.xml就可以了。

6. 依赖注入(DI)

6.1 构造器注入

  • 前面已经说了(?)

6.2 Set方式注入【重点】

  • 依赖注入:Ser注入!
    • 依赖:bean对象的创建依赖于容器
    • 注入:bean对象中的所有属性,由容器来注入

  • 环境搭建:
  1. 复杂类型
package com.zach.pojo;

public class Address {
    private String address;
    
    public String getAddress() {
        return address;
    }
    
    public void setAddress(String address) {
        this.address = address;
    }
    
    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }
}
  1. 真实测试对象
package com.zach.pojo;

import java.util.*;

public class Student {

    private String name;//通过value能赋值
    private Address address;//通过ref能赋值
    
    private String[] books;
    private List<String> hobbies;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Properties info;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public Address getAddress() {
        return address;
    }
    
    public void setAddress(Address address) {
        this.address = address;
    }
    
    public String[] getBooks() {
        return books;
    }
    
    public void setBooks(String[] books) {
        this.books = books;
    }
    
    public List<String> getHobbies() {
        return hobbies;
    }
    
    public void setHobbies(List<String> hobbies) {
        this.hobbies = hobbies;
    }
    
    public Map<String, String> getCard() {
        return card;
    }
    
    public void setCard(Map<String, String> card) {
        this.card = card;
    }
    
    public Set<String> getGames() {
        return games;
    }
    
    public void setGames(Set<String> games) {
        this.games = games;
    }
    
    public String getWife() {
        return wife;
    }
    
    public void setWife(String wife) {
        this.wife = wife;
    }
    
    public Properties getInfo() {
        return info;
    }
    
    public void setInfo(Properties info) {
        this.info = info;
    }
    
    @Override
    public String toString() {
        return "Student{" +
                "\nname='" + name + '\'' +
                ", \naddress=" + address.toString() +
                ", \nbooks=" + Arrays.toString(books) +
                ", \nhobbies=" + hobbies +
                ", \ncard=" + card +
                ", \ngames=" + games +
                ", \nwife='" + wife + '\'' +
                ", \ninfo=" + info +
                '}';
    }
}
  1. beans.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<bean id="student" class="com.zach.pojo.Student">
		<!--第一种:普通值注入,使用value-->
		<property name="name" value="张天道"/>
	</bean>
	
	
	
</beans>
  1. 测试类MyTest
import com.zach.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Student student = (Student) context.getBean("student");
        System.out.println(student.toString());
    }
}
        //Student{name='张天道',
        // address=null, books=null, hobbies=null,
        // card=null, games=null, wife='null', info=null}
  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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<bean id="address" class="com.zach.pojo.Address">
		<property name="address" value="天山or蜀山"/>
	</bean>
	
	<bean id="student" class="com.zach.pojo.Student">
		<!--第一种:普通值注入,使用value-->
		<property name="name" value="张天道"/>
		
		<!--第二种:Bean注入,使用ref-->
		<property name="address" ref="address"/>
		
		<!--数组注入,使用array,value-->
		<property name="books">
			<array>
				<value>《红楼梦》</value>
				<value>《西游记》</value>
				<value>《水浒传》</value>
				<value>《三国演义》</value>
			</array>
		</property>
		
		<!--List注入,使用list,value-->
		<property name="hobbies">
			<list>
				<value></value>
				<value></value>
				<value></value>
				<value></value>
				<value></value>
				<value>写bug</value>
			</list>
		</property>
		
		<!--Map注入,使用map,entry-->
		<property name="card">
			<map>
				<entry key="身份证" value="000000199809250000"/>
				<entry key="银行卡" value="6222620000000000407"/>
			</map>
		</property>
		
		<!--Set注入,使用set,value-->
		<property name="games">
			<set>
				<value>王者荣耀</value>
				<value>绝地求生</value>
				<value>炉石传说</value>
				<value>守望先锋</value>
				<value>OW</value>
			</set>
		</property>
		
		<!--null注入,使用null-->
		<property name="wife">
			<null/>
		</property>
		
		<!--Properties注入,使用props-->
		<property name="info">
			<props>
				<prop key="学号">2016022318</prop>
				<prop key="姓名">张天道</prop>
				<prop key="性别"></prop>
				
				<prop key="driver">driver</prop>
				<prop key="url">url</prop>
				<prop key="username">root</prop>
				<prop key="password">123456</prop>
			</props>
		</property>
	</bean>
	
	
	
</beans>
  • 输出:(只有info的顺序乱了,不知为何)
Student{
name='张天道', 
address=Address{address='天山or蜀山'}, 
books=[《红楼梦》, 《西游记》, 《水浒传》, 《三国演义》], 
hobbies=[,,,,, 写bug], 
card={身份证=000000199809250000, 银行卡=6222620000000000407}, 
games=[王者荣耀, 绝地求生, 炉石传说, 守望先锋, OW], 
wife='null', 
info={学号=2016022318, 性别=, password=123456, url=url, driver=driver, 姓名=张天道, username=root}}

6.3 拓展方式注入

  • 我们可以使用p命名空间和c命名空间进行注入
  • 官方解释:
    在这里插入图片描述
  • 需要导入一下两段:
    • xmlns:p="http://www.springframework.org/schema/p"
    • xmlns:c="http://www.springframework.org/schema/c"
  • 使用:
<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!--p命名空间注入,可以直接注入属性的值:property-->
	<bean id="user" class="com.zach.pojo.User" p:name="张天道" p:age="28"/>
	
	<!--c命名空间注入,是通过构造器注入属性的值:construct-args-->
	<bean id="user2" class="com.zach.pojo.User" c:name="张酬勤" c:age="18"/>
</beans>
  • 测试:
    @Test
    public void test2(){
        ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
        User user = context.getBean("user", User.class);
        System.out.println(user.toString());
    }
    
    @Test
    public void test3(){
        ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
        User user = context.getBean("user2", User.class);
        System.out.println(user.toString());
    }
  • 注意点:p和c命名空间不能直接使用,需要导入上面提到的xml约束
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"

6.4 bean的作用域

在这里插入图片描述

  1. 单例模式(Spring默认机制,不写就是单例)
  • 每次从容器中get的时候,都会使用同一个对象
	<bean id="user2" class="com.zach.pojo.User" c:name="张酬勤" c:age="18" scope="singleton"/>
  • 单线程一般用单例,性能高,但也可能出现并发问题(延迟、输出不一致…)。
    在这里插入图片描述
  1. 原型模式:
  • 每次从容器中get的时候,都会产生一个新对象
	<bean id="user2" class="com.zach.pojo.User" c:name="张酬勤" c:age="18" scope="prototype"/>
  • 多线程一般用原型,性能低(浪费资源)。
    在这里插入图片描述
  1. 其余的request、session、application,这些只能在web开发中使用到。

7. Bean的自动装配

  • 自动装配是Spring满足bean依赖的一种方式。
  • Spring会在上下文中自动寻找,并自动给bean装配属性。

  • 在Spring中有三种装配的方式:
    • 在xml中显式地配置(上面的)
    • 在Java中显式地配置(未遇到的)
    • 隐式地自动装配bean【重要】

7.1 测试

  • 环境搭建:一人三宠物。
package com.zach.pojo;

public class Person {
    
    private String name;
    private Cat cat;
    private Dog dog;
    private Fox fox;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public Cat getCat() {
        return cat;
    }
    
    public void setCat(Cat cat) {
        this.cat = cat;
    }
    
    public Dog getDog() {
        return dog;
    }
    
    public void setDog(Dog dog) {
        this.dog = dog;
    }
    
    public Fox getFox() {
        return fox;
    }
    
    public void setFox(Fox fox) {
        this.fox = fox;
    }
    
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", cat=" + cat +
                ", dog=" + dog +
                ", fox=" + fox +
                '}';
    }
}
package com.zach.pojo;

public class Cat {
    private String name;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                '}';
    }
    
    public void say(){
        System.out.println("喵喵喵~ or meow~ ...");
    }
}
package com.zach.pojo;

public class Dog {
    private String name;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                '}';
    }
    
    public void say(){
        System.out.println("汪汪汪~ or ruff~ ...");
    }
}
package com.zach.pojo;

public class Fox {
    private String name;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    public String toString() {
        return "Fox{" +
                "name='" + name + '\'' +
                '}';
    }
    
    public void say(){
        System.out.println(
                "Ring-ding-ding-ding-dingeringeding or " +
                "Wa-pa-pa-pa-pa-pa-pow or " +
                "Hatee-hatee-hatee-ho...");
    }
}
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<bean id="cat" class="com.zach.pojo.Cat">
		<property name="name" value="小炎"/>
	</bean>
	
	<bean id="dog" class="com.zach.pojo.Dog">
		<property name="name" value="木木云力"/>
	</bean>
	
	<bean id="fox" class="com.zach.pojo.Fox">
		<property name="name" value="貂爷"/>
	</bean>

	<bean id="person" class="com.zach.pojo.Person">
		<property name="name" value="林动"/>
		<property name="cat" ref="cat"/>
		<property name="dog" ref="dog"/>
		<property name="fox" ref="fox"/>
	</bean>
	
</beans>
    @Test
    public void test1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Person person = context.getBean("person", Person.class);
        System.out.println(person.toString());
        person.getCat().say();
        person.getDog().say();
        person.getFox().say();
    }

7.2 ByName自动装配

  • autowire=“byName”
	<!--byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的bean id!-->
	<bean id="person" class="com.zach.pojo.Person" autowire="byName">
		<property name="name" value="林动"/>
	</bean>

7.3 ByType自动装配

  • autowire=“byType”
	<bean id="dog" class="com.zach.pojo.Dog">
		<property name="name" value="木木云力"/>
	</bean>
	
	<bean class="com.zach.pojo.Fox">
		<property name="name" value="貂爷"/>
	</bean>

	<!--byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的bean id!-->
	<!--byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean!所以上面不写id="fox"也可以-->
	<bean id="person" class="com.zach.pojo.Person" autowire="byType">
		<property name="name" value="林动"/>
	</bean>
  • 小结:
    • byName的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致。
    • byType的时候,需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性的类型一致。

7.4 使用注解实现自动装配

  • jdk1.5起支持注解,spring2.5起支持注解。
  • The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML.
  • 基于注释的配置的引入提出了这种方法是否比 XML“更好”的问题。
  • 注解使用须知:
    • 导入约束:context约束
    • 配置注解的支持:<context:annotation-config/>
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
	
	<!--开启注解支持-->
	<context:annotation-config/>



</beans>
  • @Autowired注解
    • 直接在属性上使用即可,也可以在set方法上使用。
    • 使用Autowired,我们可以不写set方法,前提是这个自动装配的属性在IOC(Spring)容器中存在,且符合类型byType
  • 科普:
@Nullable //当字段标记了这个注解,说明这个字段可以为null。(但没有测试成功)
public @interface Autowired {
    boolean required() default true;
}
  • 测试代码
  • Person
public class Person {
    private String name;
    
    //如果显式地定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空。
    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;
    @Autowired
    private Fox fox;
  • 如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候,我们可以使用【@Qualifier(value=“”)】去配合@Autowired一起使用,指定一个唯一的bean对象注入。
public class Person {
    private String name;

    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;
    @Autowired
    @Qualifier(value = "fox")
    private Fox fox;
  • @Resource注解 ,Java的注解
public class Person {
    private String name;
    
    @Autowired
    private Cat cat;
    @Autowired
    @Resource(name = "dog")
    private Dog dog;
    @Autowired
    @Qualifier(value = "fox")
    private Fox fox;
  • 小结:
    • @Resource 和 @Autowired 的区别:
      • 都是用来自动装配的,都可以放在属性字段上。(都常用)
      • @Autowired 默认通过byType 的方式实现,而且必须要求这个对象存在!(但是如果不能唯一自动装配上属性,则需要通过@Qualifier(value=“”)装配名字)
      • @Resource 默认则通过byName的方式实现,但是如果找不到名字,还能通过byType实现!两种都找不到则报错。
      • 执行顺序不同:@Autowired 默认通过byType的方式实现,@Resource 默认通过byName的方式实现。

8. 使用注解开发

  • 在Spring4之后,要使用注解开发,必须要保证aop的包导入了。
    在这里插入图片描述
  • 使用注解需要导入context约束,增加注解的支持。
<?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
        https://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.zach.pojo"/>
	<!--开启注解支持-->
	<context:annotation-config/>



</beans>

8.1 bean

8.2 属性如何注入

//等价于<bean id="user" class="com.zach.pojo.User"/>
    //@Component组件
@Component
public class User {
    
    public String name;
    
    //相当于<property name="name" value="张天道"/>
    @Value("张天道")
    public void setName(String name) {
        this.name = name;
    }
}

8.3 衍生的注解

  • @Component 有几个衍生注解,我们在web开发中,会按照mvc三层架构分层!
    • dao【@Repository】
    • service【@Service】
    • controller【@Controller】
  • 这四个注解的功能都一样的,都是代表将某个类注册到Spring中,装配Bean

8.4 自动装配配置

  • @Autowired
    • 自动装配,通过类型或名字。
    • 先通过类型,如果不能唯一自动装配上属性,则需要通过@Qualifier(value=“”)装配名字。
  • @Nullable
    • 字段标记了这个注解,说明该字段可为null
  • @Resource
    • 自动装配,通过名字或类型。
    • 先通过byName,但是如果找不到名字,还能通过byType实现!

8.5 作用域

//等价于<bean id="user" class="com.zach.pojo.User"/>
    //@Component组件
@Component
@Scope("singleton")
public class User {
    
    public String name;
    
    //相当于<property name="name" value="张天道"/>
    @Value("张天道")
    public void setName(String name) {
        this.name = name;
    }
}

8.6 小结

  • xml 与 注解:
    • xml:更加万能,适用于任何场合!维护简单方便。
    • 注解:不是自己的类使用不了,维护相对复杂。
  • xml 与 注解的最佳实践:
    • xml:用来管理bean
    • 注解:只负责完成属性的注入
    • 在使用过程中,主要注意一个问题:让注解生效的必要条件:开启注解支持!
	<!--指定要扫描的包,在这个包下的注解就会生效-->
	<context:component-scan base-package="com.zach"/>
	<!--开启注解支持-->
	<context:annotation-config/>

9. 使用Java的方式配置Spring

  • 我们现在完全可以不用Spring的xml配置,而全权交给Java来做!

  • JavaConfig是Spring的一个子项目,在Spring4之后,它成为了一个核心功能。
    在这里插入图片描述

  • User(实体类)

package com.zach.pojo;

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

//该注解含义:将该类注册到容器中,由Spring接管。
@Component
public class User {
    @Value("张天道")//注入属性的值,这里是name的值
    private String name;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}
  • ZachConfig(配置文件(配置类))
package com.zach.config;

import com.zach.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

//该注解含义:将该类注册到容器中,由Spring接管,因为它本身也是被加了注解@Component了
    //所以,加了注解@Configuration后,代表这是一个配置类,和之前的beans.xml类似。
@Configuration
@ComponentScan("com.zach")
@Import(ZachConfig2.class)
public class ZachConfig {
    
    //注册一个bean,就相当于之前写的bean标签
    //该方法的名字,就相当于bean标签的id属性
    //该方法的返回值,就相当于bean标签的class属性
    @Bean
    public User user(){
        return new User();//这里返回的就是要注入到bean的对象
    }
}
  • MyTest(测试类)
import com.zach.config.ZachConfig;
import com.zach.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        //如果完全使用了配置类方式去做,我们就只能通过AnnotationConfigApplicationContext上下文来获取容器,
            //通过配置类的class对象加载!
        ApplicationContext context = new AnnotationConfigApplicationContext(ZachConfig.class);
        User user = context.getBean("user", User.class);
        System.out.println(user.getName());
    }
}
  • 这种纯Java的配置方式,在SpringBoot中随处可见!

 
 

—————— THE END ——————
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Zachsj

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

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

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

打赏作者

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

抵扣说明:

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

余额充值