小白学习spring第一天

第二章:Spring

第1节:概述

1.1 介绍 heap stack
Spring是一个分层的Java SE/EE full-stack(一站式)轻量级开源框架,以 IoCInverse Of Control:控制反转)和 AOP(Aspect Oriented Programming:面向切面编程)为内核。
在java三层架构当中分别提供了相应技术:
表现层(web层)      :SpringMVC 框架,servlet
业务层(service层)  :Bean管理(IOC容器,在三层都有体现) 声明式事务
持久层(dao层)      :JdbcTemplate模板对象以及提供了ORM模块整合其他优秀的持久层技术

spring 框架: 
分层一站式框架  轻量   开源 
AOP IOC
1.2 发展历程
1997 年, IBM提出了EJB 的思想
1998 年,SUN制定开发标准规范 EJB1.0
1999 年,EJB1.1 发布
2001 年,EJB2.0 发布
2003 年,EJB2.1 发布
2006 年,EJB3.0 发布

Rod JohnsonSpring 之父)
Expert One-to-One J2EE Design and Development(2002)
阐述了 J2EE 使用EJB 开发设计的优点及解决方案
Expert One-to-One J2EE Development without EJB(2004)
阐述了 J2EE 开发不使用 EJB的解决方式(Spring 雏形)

20179 月份发布了 Spring 的最新版本 Spring5.0 通用版(GA)
1.3 优势
1. 方便解耦,简化开发:Spring 就是一个大工厂,可以管理所有对象的创建和依赖关系维护,交给Spring管理
2. AOP 编程的支持:可以方便的实现对程序进行权限拦截,日志记录,运行的监控
3. 声明式事务的支持:通过配置方式完成对事务的管理,无需手动编程
4. 方便程序的测试:对Junit支持,可以通过注解方便的对Spring程序进行测试
5. 整合外部优秀技术:Spring内部提供了对各种优秀框架(HibernateMybatisQuartz等)的直接支持
6. javaEE技术的封装 :Spring对javaEE开发当中复杂难用的API(JavaEmail, RMI等)进行封装,降低了这些API的使用难度。
1.4 体系结构
  Spring的核心是容器(IOC):  Beans Core Context SpEL表达式
  中间层技术:AOP Aspects AOP
  web: servler  springmvc 
  data Access: 数据访问层: jdbc  ORM 整合外部的优秀框架 Transaction 事务
  基于Test测试: spring 整合junit junit4.X 
  
  官方网站: 
  https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#spring-core

在这里插入图片描述

第2节:程序的耦合和解耦合

2.1 什么是程序的耦合
话术:
程序的耦合是程序之间的关联性,也就是多个类的联系是否紧密,多个对象之间的关系是否密切。

耦合度高: 
(1)不利于扩展
(2)不利于程序的维护。

生活中的案例: 
你的房子里面有窗子,那么房子和窗子就有了关联

	耦合度是松还是紧就看你的关联是强还是弱,也就是修改的代价,比如你窗子是扣死在墙里的那么你修改窗子就必须修改墙 这就比较紧密了,反应在程序上就是耦合度高,不利于程序的扩展和维护。
	但是如果你窗子是按照某种规格的 可以自由拆装的,那么修改的代价就小,耦合度也就低了,反应在程序上就是耦合度低,利于程序的扩展和维护。

我们写程序的目标就是 高内聚 低耦合!
这样修改起来 就不会有太多的联系,不用改一个地方其他的都要修改。

2.2 解决程序耦合的思路
2.2.1 编译不依赖,运行时才依赖
当我们讲解jdbc时,是通过反射来注册驱动的,代码如下:
Class.forName("com.mysql.jdbc.Driver");//使用的驱动类是指定了一个字符串
底层: DriverManager.regist(new com.mysql.jdbc.Driver());
Connection connection = DriverManager.getConnection("","","");
 	此时的好处式,我们的类中在编译阶段不再需要具体的驱动类,就算删除mysql的驱动jar包,依然可以通过编译。在运行阶段才会依赖驱动包。实际开发当中,我们应该做到编译不依赖,运行时才依赖。
  上述代码产生的新问题,mysql驱动类的全限定类名作为一个字符串java类中是写死的,一旦发生改变,还需要修改源码。

  使用配置文件结合反射就可以解决上述问题。      
2.2.2 使用工厂模式解耦合
 在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的 方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。 

那么,这个读取配置文件,创建和获取三层对象的类就是工厂。

service 调用dao:  

原生:  new xxxDaoImpl();  问题: service实现类当中出现了 new关键字, 出现了dao 层具体的实现类。 不满足java设计原则: 面向接口开发~  总结: 耦合度高~ 

工厂模式: XXXFactory.getInstance(); 获得接口的实现类: xxxDao接口接收~  解决了: new关键字, 业务层的实现类当中, 不在出现dao层的实现类。  总结: 松耦合~ 

第3节:IOC 机制

3.1 IOC的简介
SpringIOC:IOC 是 Inversion of Control 的缩写,多数书籍翻译成“控制反转”,还有些书籍翻译成为“控制反向”或者“控制倒置”。

就是将对象的创建和维护的权利交给spring 框架。 

1996 年,Michael Mattson 在一篇有关探讨面向对象框架的文章中,首先提出了 IOC 这个概念。简单来说就是把复杂系统分解成相互合作的对象,这些对象类通过封装以后,内部实现对外部是透明的,从而降低了解决问题的复杂度,而且可以灵活地被重用和扩展。

IOC 理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦 如下图

在这里插入图片描述

		大家看到了吧,由于引进了中间位置的“第三方”,也就是IOC容器,使得ABCD4个对象没有了耦合关系,齿轮之间的传动全部依靠“第三方”了, 全部对象的控制权全部上缴给“第三方”IOC容器,所以,IOC容器成了整个系统的关键核心,它起到了一种类似“粘合剂”的作用,把系统中的所有对象粘合 在一起发挥作用,如果没有这个“粘合剂”,对象与对象之间会彼此失去联系,这就是有人把IOC容器比喻成“粘合剂”的由来。
我们再来做个试验:把上图中间的IOC容器拿掉,然后再来看看这套系统:

在这里插入图片描述

		我们现在看到的画面,就是我们要实现整个系统所需要完成的全部内容。这时候,ABCD4个对象之间已经没有了耦合关系,彼此毫无联系,这样的话, 当你在实现A的时候,根本无须再去考虑BCD了,对象之间的依赖关系已经降低到了最低程度。所以,如果真能实现IOC容器,对于系统开发而言,这将是 一件多么美好的事情,参与开发的每一成员只要实现自己的类就可以了,跟别人没有任何关系!

总结: 
	IOC容器就是创建对象, 并且维护对象和对象之间的关联关系。
3.2 IOC作用
		IOC本质上就是一个大工厂,大容器。主要作用就是创建和管理对象的依赖关系,削减计算机程序的耦合(解除我们代码中的依赖关系),提高程序的可扩展性和可维护性。
3.3 IOC入门
3.3.1 构建工程添加依赖
<properties>
        <spring.version>5.2.5.RELEASE</spring.version>
    </properties>
    <!--导入spring的context坐标,context依赖core、beans、expression aop-->
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>
3.3.2 创建持久层接口和实现类
public interface UserDao {    
    public void save();
}

public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("userDao save method running...... ");
    }
}

3.3.3 创建业务层接口和实现类
public interface UserService {    
    public void saveService();
}

public class UserServiceImpl implements UserService {
    @Override
    public void saveService() {
        System.out.println("userSerivce save method running......");
    }
}

3.3.4 创建IOC配置文件
xml文件名称: applicationContext.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">

</beans>
3.3.5 配置文件管理对象
<?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">

    <!--配置userDaoImpl-->
    <bean id="userDao" class="com.ujiuye.dao.impl.UserDaoImpl"></bean>
    <!--配置userServiceImpl-->
    <bean id="userService" class="com.ujiuye.service.UserServiceImpl"></bean>
</beans>
3.3.6 测试
    @Test
    public void test1(){
        //1:获得spring IOC容器对象:
        ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        //2:从容器当中根据id获得UserDaoImpl 对象,执行userDao对象的save方法
        UserDao userDao = (UserDao) applicationContext.getBean("userDao");
        userDao.save();
        //3:从容器当中根据id获得UserServiceImpl 对象,执行userService对象的saveService方法
        UserService userService = (UserService)applicationContext.getBean("userService");
        userService.saveService();
    }

运行结果: 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zu3nHWrz-1666881307897)(.\images\运行结果1.png)]

第4节:基于XML的IOC

4.1 IOC配置文件详解
bean标签: 用于配置对象交给Spring 来创建。
默认情况下他会调用类中无参数的构造器,如果没有无参数构造器则不能成功创建 
基本属性: 
id      :  Bean实例对象在Spring容器当中的唯一标识
class   :  Bean的全限定类名
name    :  了解,给对象命名操作
4.2 源码解析
4.2.1 IOC容器解析(面试题目)
IOC思想基于IOC容器完成,IOC容器底层就是对象工厂,Spring 中工厂的类结构图如下:

在这里插入图片描述

1. BeanFactory :该接口是顶层接口, IOC容器的基本实现,是Spring内部使用的接口,不提供开发人员使用,加载配置文件时,不会创建对象,在获得(使用)对象时才采取创建对象。对象的创建时机,getBean()创建【稍后演示】

2. HierarchicalBeanFactory:这个工厂接口非常简单,实现了Bean工厂的分层。 工厂接口也是继承自BeanFacotory,也是一个二级接口,相对于父接口,它只扩展了一个重要的功能——工厂分层

3. AutowireCapableBeanFactory:该接口有自动装配能力,需要注意的是,ApplicationContext接口并没有实现此接口,因为应用代码很少用到此功能,如果确实需要的话,可以调用ApplicationContext的getAutowireCapableBeanFactory方法,来获取此接口的实例。 

4. ListableBeanFactory:获取bean时,Spring 鼓励使用这个接口定义的api,如查看Bean的个数、获取某一类型Bean的配置名、查看容器中是否包括某一Bean等方法。

5. ApplicationContextBeanFactory接口的子接口,提供更多强大的功能,一般由开发人员使用.接口提供了bean基础性操作同时,扩展了国际化等功能。ApplicationContext接口在加载配置文件时候就会配置文件当中的对象进行创建,存放在IOC容器当中

6. AnnotationConfigApplicationContext:   
   当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。

7. ClassPathXmlApplicationContext: 
   它是从类的根路径下加载配置文件 推荐使用这种

8. FileSystemXmlApplicationContext: 
   它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
重点掌握: BeanFactory ApplicationContext

面试题目:  BeanFactory & ApplicationContext 联系和区别: 

BeanFactory : 顶层接口, 接口当中实现了基础性的功能。 提供给框架设计者使用。 

                             加载配置文件的时候, 对象不创建。 getBean();才会创建对象。 

ApplicationContext :是BeanFactory 接口的子接口。 提供了基础性功能之外, 功能进行了扩展,开发者使用。

                              加载配置文件的时候, 对象就创建成功, 并且存放在IOC 容器当中。 

ClassPathXmlApplicationContext: 从类路径下获得资源文件。 

AnnotationConfigApplicationContext: 基于主机模式使用的实现类。 

第5节:手动实现自己的IOC容器

5.1 分析IOC 实现思路
思路:
 1、创建工厂对象,加载Spring核心配置文件
 2、使用xml解析技术,获得bean标签当中id属性以及class属性对应的值
 3、底层使用反射技术,创建对象
 4、准备临时容器,存放创建的对象
 5、提供getBean方法,对外提供对象
 6、测试自定义的工厂对象

在这里插入图片描述

5.2 设计接口、类和配置文件
//设定UserDao接口
public interface UserDao {
    public void save();
}
//设定UserDao接口实现类
public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("userDao save method running...... ");
    }
}
5.3 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean id="userDao" class="com.offcn.dao.impl.UserDaoImpl"></bean>
    <bean id="userService" class="com.offcn.service.impl.UserServiceImpl"></bean>
</beans>
5.4 解析配置文件
dom4J, jdom sax jaxp 解析器
<!--引入dom4J-->
<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>
/**
 * 创建自己的工厂类
 */
public class MyBeanFactory {

    //创建一个map集合,模拟IOC容器
    private static Map<String,Object> map = new HashMap<>();

    static{
        try {
            //使用dom4J 解析xml文件:
            //第一步:获得一个解析器:
            SAXReader reader = new SAXReader();
            //第二: 读取外部的配置文件:
            String path = "src/main/resources/myApplicationContext.xml";
            //第三: 读取了整个文档对象
            Document document = reader.read(path);
            //第四: 获得根节点:
            Element rootElement = document.getRootElement();//beans
            //第五: 获得根节点下的所有的bean 标签对应的节点:
            List<Element> bean = rootElement.elements("bean");// bean
            for (Element element : bean) {
                //获得id属性对应的值:
                String id1 = element.attributeValue("id");
                //获得class属性对应的值:【全限定类名】
                String aClass = element.attributeValue("class");//获得class对应的值: 全限定类名。
                //通过反射创建对象:
                Class  clz = Class.forName(aClass);
                Object object = clz.newInstance();
                //存容器 id做key,创建出来的对象value
                map.put(id1,object);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据id从容器当中获得对象
     * @param id id的名称
     * @return 返回Object类型对象
     */
    public static Object getBean(String id){
        Object o = map.get(id);
        return o;
    }

}

总结: IOC容器自定义时候; 
xml解析技术: 
反射技术
工厂模式
5.5 测试
@Test
public void testMyFactory(){
    //1:创建工厂对象
    MyBeanFactory factory =new MyBeanFactory();
    //2:从容器当中根据id获得对象
    UserDao userDao = (UserDao) factory.getBean("userDao");
    System.out.println(userDao);
    userDao.save();
}
运行结果: 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xHx59dsX-1666881307900)(./images/运行结果2.png)]

第6节:管理bean细节

6.1 bean实例化介绍
bean 对象创建~ 
6.2 bean实例化方式【面试问题】
6.2.1 构造方法的方式
它会根据默认无参构造函数来创建类对象。如果 bean 中没有默认无参构造函数,将会创建失败
(1)创建User类
public class User implements Serializable {
    public User(){
        System.out.println("user created...");
    }
}
(2)配置容器管理对象
<!--配置user对象-->
<bean id="user" class="com.ujiuye.pojo.User"></bean>
(3)测试实例化对象
    @Test
    public void testUser(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) context.getBean("user");
        System.out.println(user);
    }
6.2.2 静态工厂方式
(1)创建静态工厂
public class ItemFactory {

    //静态方法返回实例bean
    public static User createUser(){
        System.out.println("static method running create bean ......");
        return new User();
    }
}
(2)配置容器管理对象
<!--静态工厂实例化对象:
   工厂方法的返回值存放在IOC容器当中
-->
<bean id="user" class="com.ujiuye.factory.ItemFactory" factory-method="createUser"></bean>
(3)测试实例化对象
    @Test
    public void testItemFactory(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) context.getBean("user");
        System.out.println(user);
    }
6.2.3 实例工厂方式
(1)创建实例工厂
public class NewItemFactory {
    //工厂的非静态方法返回bean实例
    public User createUser(){
        System.out.println("Dynamic method running create bean ......");
        return new User();
    }
}
(2)配置容器管理对象
<!--实例工厂:
   步骤一; 创建对象
   步骤二: 通过对象调用方法,方法的返回值存在IOC容器当中。 
-->
 <bean id="itemFactory" class="com.ujiuye.factory.NewItemFactory"></bean>
 <bean id="user" factory-bean="itemFactory" factory-method="createUser"></bean>
(3)测试实例化对象
    @Test
    public void testNewItemFactory(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) context.getBean("user");
        System.out.println(user);
    }
6.3 bean作用域【面试问题】
6.3.1 bean作用域介绍

所谓Bean的作用域其实就是指Spring给我们创建出的对象的存活范围,在配置文件中通过bean的scope属性指定
<bean id="" class="" scope="">
scope:指对象的作用范围,取值如下: 

取值范围说明
singleton默认值,单例的
prototype多例的
requestWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中
sessionWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中
global sessionWEB 项目中,应用在 Portlet 环境,如果没有 Portlet 环境那么globalSession 相当于 session
6.3.2 bean作用域的解析
(1)scope取值为singleton
 Bean的实例化个数:1Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
(2)scope取值为prototype
 Bean的实例化个数:多个
 Bean的实例化时机:当调用getBean()方法时实例化Bean 
注意: 多例对象,不会随容器而创建, 不会随容器销毁而销毁。 
	在内存当中, 由垃圾回收器定期回收~
(3)Scope取值为其他值
scope指定为其他值,需要在特定的环境下使用, 只需要作为一个了解知识,面试能够回答出来即可
6.4 bean的生命周期
6.4.1 bean生命周期介绍
在这里所谓的Bean的生命周期其实指的是Bean创建到销毁的这么一段时间。 
在Spring中可以通过配置的形式,指定bean在创建后和销毁前要调用的方法。
属性:
init-method:指定bean在创建后调用的方法
destroy-method:对象在销毁前调用的方法
<bean id="xxx" class="xxx" init-method="" destroy-method=""></bean>
6.4.2 单例对象的生命周期
(1)添加方法init和destory
public class UserServiceImpl implements UserService {
    public void init(){
        System.out.println("init method running...");
    }
    @Override
    public void saveService() {
        System.out.println("userSerivce save method running......");
    }

    public void destroy(){
        System.out.println("destroy method running...");
    }
}
(2)配置文件中配置UserService
<!--配置userServiceImpl-->
<bean id="userService" class="com.ujiuye.service.UserServiceImpl" init-method="init" destroy-method="destroy">
    
</bean>
(3)测试单例对象生命周期
@Test
    public void test1(){
        ClassPathXmlApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.saveService();
        //关闭工厂:
        applicationContext.close();
    }
单例对象总结: 

对象创建:当应用加载,创建容器时,对象就被创建了

对象运行:只要容器在,对象一直活着

对象销毁:当应用卸载,销毁容器时,对象就被销毁了

6.4.3 多例对象的生命周周期
(1)配置文件scope属性
 <!--配置userServiceImpl-->
 <bean id="userService" class="com.ujiuye.service.UserServiceImpl" init-method="init" destroy-method="destroy" scope="prototype"></bean>
(2)测试多例对象生命周期
@Test
public void test1(){
    ClassPathXmlApplicationContext applicationContext =
        new ClassPathXmlApplicationContext("applicationContext.xml");
    UserService userService = (UserService) applicationContext.getBean("userService");
    userService.saveService();
    //关闭工厂:
    applicationContext.close();
}
多例对象总结: 

对象创建:当使用对象时(getBean),创建新的对象实例

对象运行:只要对象在使用中,就一直活着

对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了, 对destroy-method属性针对多例不生效。

第7节:依赖注入

7.1 介绍

依赖注入(Dependency Injection):简称DI,它是 Spring 框架核心 IOC 的具体实现。
在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。
IOC 解耦只是降低他们的依赖关系,但不会消除。
例如:业务层仍会调用持久层的方法。
那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。
简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取

简单理解: 依赖注入就是spring IOC 容器在创建对象的时候, 给属性赋值。 

7.2 依赖注入方式
7.2.1 构造函数注入
(1)创建实体类
	顾名思义,就是使用类中的构造函数,给成员变量赋值。注意,赋值的操作不是我们自己做的,而是通过配置
的方式,让 Spring 框架来为我们注入。具体代码如下
public class Account {
    private String name;
    private Integer age;
    private Date birthday;

    public Account(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }
}
(2)配置文件管理类
<!--使用构造函数的方式:给account中的属性赋值
        要求:
            类中需要提供一个对应参数列表的构造器函数
        涉及的标签:
            constructor-arg:
             属性:
             name: 执行参数在构造器中的名称
             value:它能赋的值是基本数据类型和 String 类型
             ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean
    -->
<bean id="now" class="java.util.Date"></bean>
<bean id="account" class="com.ujiuye.pojo.Account">
    <constructor-arg name="name" value="王达"></constructor-arg>
    <constructor-arg name="age" value="20"></constructor-arg>
    <constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
(3)构造函数注入测试
@Test
public void testDI(){
    ClassPathXmlApplicationContext applicationContext =
        new ClassPathXmlApplicationContext("applicationContext.xml");
    Account account = (Account) applicationContext.getBean("account");
    System.out.println("name:"+account.getName()+" age:"+account.getAge()+" birthday:"+account.getBirthday());
    //打印结果: name:王达 age:20 birthday:Thu Feb 04 13:53:45 CST 2021
}
7.2.2 setter注入
(1)修改类添加setter方法
顾名思义,就是在类中提供需要注入成员的 set 方法。具体代码如下:
public class Account {
    private String name;
    private Integer age;
    private Date birthday;
    
    public Account() {
    }

    public Account(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}
(2)注入依赖数据
<!--使用set方法的方式给属性赋值
        涉及的标签:
            property
            属性:
               name:找的是类中set方法后面的部分
               ref: 给属性赋值是其他bean类型的
               value:给属性赋值是基本数据类型和 string 类型的
             实际开发当中, 此种方式用的比较多,推荐使用
           -->
<bean id="now" class="java.util.Date"></bean>
<bean id="account" class="com.ujiuye.pojo.Account">
    <property name="name" value="张三丰"></property>
    <property name="age" value="31"></property>
    <property name="birthday" ref="now"></property>
</bean>
(3)setter注入测试方法
@Test
public void testDI(){
    ClassPathXmlApplicationContext applicationContext =
        new ClassPathXmlApplicationContext("applicationContext.xml");
    Account account = (Account) applicationContext.getBean("account");
    System.out.println("name:"+account.getName()+" age:"+account.getAge()+" birthday:"+account.getBirthday());
    //测试结果: name:张三丰 age:31 birthday:Thu Feb 04 14:05:19 CST 2021
}
 
7.2.3 P名称空间注入
语法: p:属性名称=“”  
在xml当中引入p名称空间
xmlns:p="http://www.springframework.org/schema/p"

语法: 
<bean id="account" class="com.offcn.pojo.Account" p:name="唐晓飞" p:age="21" p:birthday-ref="birthday"></bean>

7.2.4 SPEL 表达式注入
<!--SPEL注入: spring el expression
       (1)  底层是调用了set方法
       (2)  #{} spring EL 语法
       (3)  不管是普通属性或者是对象属性, 都使用value 赋值。
       (4)功能最强大 , 属性赋值的时候,可以调用对象的属性, 可以调用对象的方法。

     -->
    <bean id="account" class="com.offcn.pojo.Account">
        <property name="name" value="#{'admin'}"></property>
        <property name="age" value="#{account.calcullatorAge()}"></property>
        <property name="birthday" value="#{birthday}"></property>
    </bean>
7.3 注入集合数据
7.3.1 添加集合属性
顾名思义,就是给类中的集合成员传值,它用的也是set方法注入的方式,只不过变量的数据类型都是集合。 
我们这里介绍注入数组,List,Set,Map,Properties。具体代码如下:

public class Account {
    //注入数组,List集合,Set集合,Map集合,Properties集合属性
    private String[] myStrs;
    private List<String> myList;
    private Set<String> mySet;
    private Map<String,String> myMap;
    private Properties myProps;

    public Account() {
    }

    public String[] getMyStrs() {
        return myStrs;
    }

    public void setMyStrs(String[] myStrs) {
        this.myStrs = myStrs;
    }

    public List<String> getMyList() {
        return myList;
    }

    public void setMyList(List<String> myList) {
        this.myList = myList;
    }

    public Set<String> getMySet() {
        return mySet;
    }

    public void setMySet(Set<String> mySet) {
        this.mySet = mySet;
    }

    public Map<String, String> getMyMap() {
        return myMap;
    }

    public void setMyMap(Map<String, String> myMap) {
        this.myMap = myMap;
    }

    public Properties getMyProps() {
        return myProps;
    }

    public void setMyProps(Properties myProps) {
        this.myProps = myProps;
    }
}
7.3.2 注入依赖集合数据
<!--注入集合类型数据:
        涉及到标签:
         List结构: array list set
         Map结构:  map entry props prop
    -->
<bean id="account" class="com.ujiuye.pojo.Account">
    <!--注意:在注入集合数据时,只要是结构相同,标签可以互换-->

    <!--注入数组数据-->
    <property name="myStrs">
        <array>
            <value>array-AAA</value>
            <value>array-BBB</value>
            <value>array-CCC</value>
        </array>
    </property>
    <!--注入List集合数据-->
    <property name="myList">
        <list>
            <value>list-AAA</value>
            <value>list-BBB</value>
            <value>list-CCC</value>
        </list>
    </property>
    <!--注入Set集合数据-->
    <property name="mySet">
        <list>
            <value>set-AAA</value>
            <value>set-BBB</value>
            <value>set-CCC</value>
        </list>
    </property>
    <!--注入Map集合-->
    <property name="myMap">
        <map>
            <entry key="map-a" value="AAA"></entry>
            <entry key="map-b">
                <value>BBB</value>
            </entry>
        </map>
    </property>

    <!--注入Properties集合-->
    <property name="myProps">
        <props>
            <prop key="pro-a">AAA</prop>
            <prop key="pro-b">BBB</prop>
        </props>
    </property>
</bean>
7.3.3 集合注入测试方法
@Test
public void testDI(){
    ClassPathXmlApplicationContext applicationContext =
        new ClassPathXmlApplicationContext("applicationContext.xml");
    Account account = (Account) applicationContext.getBean("account");
    System.out.println("array:"+ Arrays.toString(account.getMyStrs()));
    System.out.println("list:"+account.getMyList());
    System.out.println("set:"+account.getMySet());
    System.out.println("map:"+account.getMyMap());
    System.out.println("props:"+account.getMyProps());
        /*
        测试结果: 
        array:[array-AAA, array-BBB, array-CCC]
        list:[list-AAA, list-BBB, list-CCC]
        set:[set-AAA, set-BBB, set-CCC]
        map:{map-a=AAA, map-b=BBB}
        props:{pro-b=BBB, pro-a=AAA}

         */
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值