博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
三、spring成长之路——springIOC容器详解(上)
阅读量:6309 次
发布时间:2019-06-22

本文共 11923 字,大约阅读时间需要 39 分钟。

目录

一、springIOC

控制反转和依赖注入

​ 简单的说就是将对象的创建,属性的的设置交给spring容器进行管理,而不再由用户自己创建,当用户需要使用该接口或者类的时候,直接注入就可以了,spring容器会自动帮助用户创建对象。

1.创建maven应用程序

【pom.xml】

​ 1.引入spring依赖,junit依赖

​ 2.引入maven插件——java编译插件

4.0.0
com.itcloud
resource
1.0-SNAPSHOT
jar
resource
http://maven.apache.org
UTF-8
org.springframework
spring-context
4.3.15.RELEASE
junit
junit
4.12
test
org.apache.maven.plugins
maven-compiler-plugin
3.7.0
1.8
1.8
UTF-8

该依赖会下载下面jar

org.springframework
spring-context
  • org.springframework:spring-aop:4.3.15.RELEASE
  • org.springframework:spring-beans:4.3.15.RELEASE
  • org.springframework:spring-core:4.3.15.RELEASE
  • org.springframework:spring-expression:4.3.15.RELEASE

2.springIOC基础

基本概念:springIOC主要作用是用来管理javaBean的容器,将java对象以及对象和对象之间的关系交由Spring容器管理。

在没有spring容器之前对接口或者类进行实例化的时候都需要使用new关键字,来进行对象的创建,那么自从有了spring,那么这些事情就交给了spring来做了。

2.1.了解spring的几种注入方式

【Teacher.java】

​ getter和setter方法在这里都会被省略。

一个老师对应多个学生,老师pojo类中包含setter注入,和List集合注入

public class Teacher implements Serializable {    private Long id;    private String name;    private Integer age;    private List
students;}

【Student.java】

一个学生对应一个老师,学生包含多种注入方式,有setter,Properties类注入,map注入以及构造方法注入

注意点,

​ 1.如果添加了有参构造方法(没有参构造),那么在进行注入的时候必须要进行构造方法的注入

​ 2.如果既有有参构造和无参构造可以不进行构造方法的注入

public class Student implements Serializable {    private Long id;    private String name;    private Teacher teacher;    private Properties pro;    private Map
map; public Student(){} public Student(Long id, String name){ this.id = id; this.name = name; }}

【applicationContext.xml】**创建spring容器

张三
1.8
70kg

【TestIOC.java】进行数据的测试,debug观察数据

package com.itcloud.pojo;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestIOC {    //加载spring容器    private ApplicationContext context =            new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");    @Test    public void testStudent() {        //context.getBean()获取spring容器中管理的bean,参数为Id        Student stu1 = (Student) context.getBean("student");        Student stu2 = context.getBean("student2", Student.class);        Teacher teacher = context.getBean("teacher", Teacher.class);        System.out.println("---------------------");    }}
2.2.p标签和c标签的注入方式

​ p代表的就是属性,c代表的就是构造方法。

添加标签头,引入p和c

xmlns:p="http://www.springframework.org/schema/p"xmlns:c="http://www.springframework.org/schema/c"

实例

c:id="3" c:name="smith"就是构造方法中的两个参数 id和name,p:teacher-ref="teacher"为类中中的属性teacher

2.3.bean之间的继承关系

两个关键字段parentabstract

1.此时student3会继承student中的id,和name属性,这个是parent的作用,非必须标签

2.abstract表示student这个bean无法被实例化,即无法再代码中获取这个bean,也无法被外部所引用,非必须标签

​ 例如:ref="student"是错的

2.4.bean的作用域

概述

作用域 描述
单例(singleton) (默认)每一个Spring IoC容器都拥有唯一的一个实例对象
原型(prototype) 一个Bean定义,任意多个对象

scope="singleton"默认值,只会产生一个实例化对象

scope="prototype"原型,每次获取bean的时候都会获取一个新的实例化对象

2.6.bean的生命周期

两个关键点:

​ 1.<bean/>标签中的字段:init-method=""表示bean初始化(构造方法)之后调用的方法 destroy-method=""容器关闭之后调用的方法.

​ 2. bean的后置处理器,需要实现方法,BeanPostProcessor这个类,两个方法:

postProcessBeforeInitialization():在每个bean初始化后(构造方法)调用一次(在init-method方法之前被调用)。

postProcessAfterInitialization():在init-method之后被调用,destroy-method之前被调用

实现案例0001

【LifeCycle.java】

package com.itcloud.pojo;public class LifeCycle {    public LifeCycle(){        System.out.println("构造方法初始化..........");    }    public void init(){        System.out.println("init()初始化方法.......");    }    public void destory(){        System.out.println("destory()销毁方法.......");    }}

【applicationContext.xml】

init-method="init" destroy-method="destory"

【TestIOC.java】测试

public class TestIOC {    //加载spring容器    private ClassPathXmlApplicationContext context =            new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");    @Test    public void testStudent() {             LifeCycle lifeCycle = context.getBean("lifeCycle", LifeCycle.class);        context.close();        //测试结果        /*信息: Loading XML bean definitions from class path resource [spring/applicationContext.xml]构造方法初始化..........init()初始化方法.......四月 08, 2018 10:09:34 上午 org.springframework.context.support.ClassPathXmlApplicationContext doClose信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@27ddd392: startup date [Sun Apr 08 10:09:33 CST 2018]; root of context hierarchydestroy()销毁方法.......        */    }}

第二个关键点实现案例0002

【CycleProcessor.java】

package com.itcloud.pojo;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;import org.springframework.stereotype.Component;public class CycleProcessor implements BeanPostProcessor {    @Override    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {        System.out.println("CycleProcessor start....." + name);        return bean;    }    @Override    public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {        System.out.println("CycleProcessor end....." + name);        return bean;    }}

【TestIOC.java】测试类不变,测试结果:

/*构造方法初始化..........CycleProcessor start.....lifeCycleinit()初始化方法.......CycleProcessor end.....lifeCycle四月 08, 2018 10:13:31 上午 org.springframework.context.support.ClassPathXmlApplicationContext doClose信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@58c1670b: startup date [Sun Apr 08 10:13:00 CST 2018]; root of context hierarchydestroy()销毁方法.......*/
2.7.工厂注入(了解即可)

注意点,如果工厂方法有参数,通过<constructor-arg value="xxx"></constructor-arg>进行参数匹配

静态工厂注入

public class StudentFactory {    public static Student getInstance(){        Student stu = new Student();        stu.setId(10L);        stu.setName("小十");        return stu;    }}

测试

Student stu = context.getBean("student6", Student.class);

实例工厂注入

package com.itcloud.pojo;public class TeacherFactory {    public Teacher getInstance(Long id, String name){        Teacher teacher = new Teacher();        teacher.setId(id);        teacher.setName(name);        return teacher;    }}
222

测试

Teacher teacher = context.getBean("teacher2", Teacher.class);

FactoryBean配置

跳转标志

package com.itcloud.pojo;import org.springframework.beans.factory.FactoryBean;public class TeacherFactoryBean implements FactoryBean {    private String name;    @Override    public Object getObject() throws Exception {        Teacher teacher = new Teacher();        teacher.setName(name);        return teacher;    }    @Override    public Class
getObjectType() { return Teacher.class; } @Override public boolean isSingleton() { return true; } public void setName(String name) { this.name = name; }}
Teacher teacher = context.getBean("teacherBean", Teacher.class);

3.spring注解注入

​ 三个注解将类注入到spring容器中,注意点:注解默认注入的Id为当前类的名称首字母小写

  • @Repository主要用于dao,数据访问层
  • @Service用于Service层,调用数据访问层的方法,进行逻辑操作
  • @Component用户普通类的注册,用户自己定义的组件

我们知道Service层一定会调用dao层的相关方法,dao层已经被注册到Spring容器之中,这是后就需要使用Spring为我们提供的注解来引用对应的实例

  • @Autowired按照类型进行匹配,如果一个接口存在两个子类,可以配合@Qualifier注解来使用
  • @Resource按照名称进行匹配,
3.1简单应用应用案例

【applicationContext-annotation.xml】支持注解配置

【UserDAO.java】

package com.itcloud.dao;public interface UserDAO {    //用户更新    int update();}

【UserDAOImpl.java】注意点:@Repository的value的值默认是(userDAOImpl)

@Repositorypublic class UserDAOImpl implements UserDAO {    @Override    public int update() {        System.out.println("进行数据库语句编写");        return 0;    }}

【UserService.java】

package com.itcloud.service;public interface UserService {    int doUpdate();}

【UserServiceImpl.java】@Service的value的默认值是:userServiceImpl

ackage com.itcloud.service.impl;import com.itcloud.dao.UserDAO;import com.itcloud.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class UserServiceImpl implements UserService {    @Autowired    private UserDAO userDAO;    @Override    public int doUpdate() {        System.out.println("UserServiceImpl update()方法开始....");        userDAO.update();        return 0;    }}

测试

context.getBean("userDAOImpl");//结果:userDAOImpl@127 即:获取到UserDAO的对象

理解bean之间的相互调用

我们在UserServiceImpl这个类中可以看到如下这句话,这句话表示的意思就是引用外部bean,在没有Spring之前我们引入外部bean的过程是:private UserDAO userDAO = new UserDAOImpl(),在有了Spring之后,spring会自动帮我们进行对象的创建,以及维护对象之间的关系。

@Autowired    private UserDAO userDAO;

测试Autowired

@Test    public void testAnnotation(){        UserService userService = context.getBean(UserService.class);        userService.doUpdate();    }//结果/*    UserServiceImpl update()方法开始....    进行数据库语句编写*/

前面提到,@Autowired是根据类型进行注入的,此时因为UserDAO只有一个子类,但是如果有两个子类要怎么书写呢:

//方案一,官方推荐    @Autowired    @Qualifier("userDAOImpl")    private UserDAO userDAO;        //方案二    @Resource(name = "userDAOImpl")    private UserDAO userDAO;    //或者    @Resource    private UserDAO userDAOImpl;
3.2理解开启注解支持配置

【applicationContext-annotation.xml】

这里也可以添加子元素,对注解数据进行过滤

最常用的过滤方式

use-default-filters="false"不使用默认过滤方式,如果为true的话,<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/> 表示的意思只是将@Service包含进来,其他注解也会包含的

4.spring引用外部属性文件

4.1 applicationContext.xml文件配置bean并且注入属性文件中的内容

【value.properties】定义一个外部属性文件

value.driverName=com.mysql.jdbc.Drivervalue.url=jdbc:mysql://localhost:3306/testvalue.username=rootvalue.password=123456

【DataSource.java】定义属性类

package com.itcloud.value;public class DataSource {    private String driverName;    private String username;    private String password;    private String url;    //getter setter方法略}

【applicationContext-annotation.xml】在spring配置文件中获取属性文件内容

此时,当spring容器加载的时候,DataSource.java 被实例化, value.properties属性文件中的内容会被注入到DataSource中。

4.2不通过配置文件的方式读取属性

【applicationContext-annotation.xml】开启注解配置

【DataSource.java】 此时可以没有setter方法

package com.itcloud.value;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;@Componentpublic class DataSource {    @Value("${value.driverName}")    private String driverName;    @Value("${value.username}")    private String username;    @Value("${value.password}")    private String password;    @Value("${value.url}")    private String url;}

转载于:https://www.cnblogs.com/hu1056043921/p/8878238.html

你可能感兴趣的文章
如何设计高扩展的在线网页制作平台
查看>>
Git 2.5增加了工作树、改进了三角工作流、性能等诸多方面
查看>>
Swift 5将强制执行内存独占访问
查看>>
中台之上(二):为什么业务架构存在20多年,技术人员还觉得它有点虚?
查看>>
深度揭秘腾讯云低功耗广域物联网LPWAN 技术及应用
查看>>
与Jeff Sutherland谈敏捷领导力
查看>>
More than React(四)HTML也可以静态编译?
查看>>
React Native最佳学习模版- F8 App开源了
查看>>
云服务正在吞噬世界!
查看>>
阅读Android源码的一些姿势
查看>>
Web语义化标准解读
查看>>
一份代码构建移动、桌面、Web全平台应用
查看>>
高性能 Lua 技巧(译)
查看>>
区分指针、变量名、指针所指向的内存
查看>>
异步编程的世界
查看>>
最近话题火爆的四件事你知道不?
查看>>
SpringBoot整合MyBatis
查看>>
云计算产业如何率先推行信用管理?
查看>>
Android 类库书签更新(一)
查看>>
Unity3D Input按键系统
查看>>