文章目录
spring学习-day01
一、IOC和DI
IOC:控制反转,把创建对象和对象之间的调用过程交给spring来管理,就是将设计好的对象交给容器来管理
eg:我们在学习spring的时候在xml配置文件中就把bean对象写好了,然后想要获取对象只要调用getBean方法就可以获取对应的对象。因为把对象生成放在了XML里定义,所以当我们需要换一个实现子类将会变成很简单,可以使耦合度降低。
DI:依赖注入就是组件之间的依赖关系由容器在运行时决定,简单点说就是容器动态的将某个依赖关系注入到组件中。再通俗点就是注入属性
二、Spring 提供 IOC 容器实现两种方式
1. BeanFactory:是spring内部的使用接口。
2. ApplicationContext:BeanFactory的一个子接口,在原来的基础上提供了更强大的功能。
BeanFactory和ApplicationContext的区别主要是:
BeanFactory在加载配置文件时不会创建对象,只有在使用的时候(即获取对象的时候)创建
对象,而ApplicationContext在加载配置文件的时候就会把配置文件中的对象给创建。
三、两种实现方式
1. 基于xml方式实现
2. 基于注解方式实现
1、基于xml方式注入属性
1) 通过set方式注入
实体类:
public class User {
/**
* 用户名
*/
private String userName;
/**
* 用户编号
*/
private String userId;
/**
* 用户邮编地址
*/
private String address;
/**
* 用户邮箱
*/
private String email;
/**
* 家乡
*/
private String countrySide;
public void setCountrySide(String countrySide) {
this.countrySide = countrySide;
}
public void setAddress(String address) {
this.address = address;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setUserId(String userId) {
this.userId = userId;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", userId='" + userId + '\'' +
", address='" + address + '\'' +
", email='" + email + '\'' +
", countrySide='" + countrySide + '\'' +
'}';
}
}
xml配置文件:
注意:这里添加了注入空值null和特殊字符的情况
<?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 ">
<!--
1、通过set方式注入
-->
<bean id="user" class="com.spring.entity.User">
<property name="userName" value="Tom"></property>
<property name="userId" value="26181"></property>
<!--
注入相关的null(空值)
-->
<property name="address">
<null></null>
<!--
<null/>
-->
</property>
<property name="email" value="2420136827@qq.com"></property>
<!--
属性值包含特殊符号,例如<>
反例:<property name="email" value="<南京>"></property>
把带特殊字符内容写到CDATA
-->
<property name="countrySide">
<value><![CDATA[<<江苏南京>>>]]]></value>
</property>
</bean>
</beans>
测试类:
@Test
public void userTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
User user = context.getBean("user", User.class);
System.out.println(user.toString());
}
对于初学者,需要提一下的是测试方法中的context.getBean(“user”, User.class)的"user"指的是配置文件中对应的id值。
测试结果:
User{userName='Tom', userId='26181', address='null', email='2420136827@qq.com', countrySide='<<江苏南京>>>]'}
2) 通过有参构造方式注入
实体类:
public class Book {
private String bookName;
private String bookPrices;
public Book(String bookName, String bookPrices) {
this.bookName = bookName;
this.bookPrices = bookPrices;
}
@Override
public String toString() {
return "Book{" +
"bookName='" + bookName + '\'' +
", bookPrices='" + bookPrices + '\'' +
'}';
}
}
xml配置文件中对应的bean实例
<!--
2、通过有参数构造方式注入
-->
<bean class="com.spring.entity.Book" id="book">
<constructor-arg name="bookName" value="假如给我三天光明"></constructor-arg>
<constructor-arg name="bookPrices" value="32.4"></constructor-arg>
</bean>
测试方法
@Test
public void bookTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
Book book = context.getBean("book", Book.class);
System.out.println(book.toString());
}
测试结果:
Book{bookName='假如给我三天光明', bookPrices='32.4'}
3) 通过p名称空间注入
注意:p名称空间注入主要是对于set方式注入的一种简化,并且观察下面的配置文件的相应变化(xmlns:p=“http://www.springframework.org/schema/p”)
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
3、通过名称空间注入
-->
<bean class="com.spring.entity.User" id="user2" p:userId="26191" p:userName="Jack"></bean>
</beans>
测试类和测试方法和上面通过set方法注入雷同。
测试结果:
User{userName='Jack', userId='26191', address='null', email='null', countrySide='null'}
4) 注入外部bean
这里使用Dao和Service来举例:
Dao层:
public interface UserDao {
void update();
}
public class UserDaoImpl implements UserDao{
@Override
public void update() {
System.out.println("update ......");
}
}
Service层:
public class UserService {
// 创建UserDao类型属性,生成set方法
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add(){
System.out.println("service add ......");
userDao.update();
}
}
配置文件:
<?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 -->
<!-- 1、service和dao对象的创建 -->
<bean class="com.spring.service.UserService" id="userService">
<!-- 注入userDao对象
name为属性只,类里面的属性名称
ref属性:注入外部bean的id值(这里是userDao)
-->
<property name="userDao" ref="userDao"></property>
</bean>
<bean class="com.spring.dao.UserDaoImpl" id="userDao"></bean>
</beans>
测试类:
@Test
public void test(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
测试结果:
service add ......
update ......
5) 注入内部bean
这里用员工和部门来举例子,一个部门有多个员工,一个员工只有一个所在部门,属于一对多的关系,我们只需要再员工类里面添加一个部门属性就可以实现。
部门类:
public class Dept {
private String deptName;
private String deptNo;
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public void setDeptNo(String deptNo) {
this.deptNo = deptNo;
}
@Override
public String toString() {
return "Dept{" +
"deptName='" + deptName + '\'' +
", deptNo='" + deptNo + '\'' +
'}';
}
}
员工类:
public class Emp {
/**
* 员工姓名
*/
private String empName;
/**
* 员工编号
*/
private String empNo;
/**
* 所在部门
*/
private Dept dept;
public void setEmpName(String empName) {
this.empName = empName;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
public void setDept(Dept dept) {
this.dept = dept;
}
/**
* 下面的getDept用于级联复制(第三种方式)
* @return
*/
public Dept getDept() {
return dept;
}
@Override
public String toString() {
return "Emp{" +
"empName='" + empName + '\'' +
", empNo='" + empNo + '\'' +
", dept=" + dept +
'}';
}
}
xml配置文件:
<!-- 注入内部bean,比如对于一对多的关系:员工Emp和部门Dept -->
<bean class="com.spring.entity.Emp" id="emp">
<property name="empName" value="小芳"></property>
<property name="empNo" value="26181"></property>
<!-- 注入内部bean -->
<property name="dept">
<bean class="com.spring.entity.Dept" id="dept">
<property name="deptName" value="公共研发部(注入内部bean)"></property>
<property name="deptNo" value="26100"></property>
</bean>
</property>
</bean>
测试:
/**
* 下面的测试是对于注入内部bean的测试
*/
@Test
public void test(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
Emp emp = context.getBean("emp", Emp.class);
System.out.println(emp);
}
结果:
Emp{empName='小芳', empNo='26181', dept=Dept{deptName='公共研发部(注入内部bean)', deptNo='26100'}}
另一种注入属性的写法:
注意:这种写法要在员工类中添加部门的getter方法,以获取对象
<!-- 级联赋值 -->
<bean class="com.spring.entity.Emp" id="emp3">
<property name="empName" value="小芳"></property>
<property name="empNo" value="26181"></property>
<!-- 1、级联赋值 -->
<property name="dept" ref="dept3"></property>
<!--
注意:这种方式要在Emp中添加Dept的getter方法来获取外部对象(dept3)
-->
<property name="Dept.deptName" value="公共研发部(级联赋值)"></property>
<property name="Dept.deptNo" value="26100"></property>
</bean>
<bean class="com.spring.entity.Dept" id="dept3"></bean>
测试:
/**
* 下面的测试是对于级联赋值的第二种写法
*/
@Test
public void test3(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
Emp emp = context.getBean("emp3", Emp.class);
System.out.println(emp);
}
结果:
Emp{empName='小芳', empNo='26181', dept=Dept{deptName='公共研发部(级联赋值)', deptNo='26100'}}
6) 集合属性的注入
1-普通集合注入
类:
public class Library {
/**
* 数组属性
*/
private String[] arrays;
/**
* List集合属性
*/
private List<String> list;
/**
* Map集合属性
*/
private Map<String,String> map;
/**
* set结合属性
*/
private Set<String> sets;
public void setArrays(String[] arrays) {
this.arrays = arrays;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setSets(Set<String> sets) {
this.sets = sets;
}
@Override
public String toString() {
return "Library{" +
"arrays=" + Arrays.toString(arrays) +
", list=" + list +
", map=" + map +
", sets=" + sets +
'}';
}
}
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 class="com.spring.entity.Library" id="library">
<!-- 对于数组属性的注入 -->
<property name="arrays">
<array>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
<value>5</value>
<value>5</value>
</array>
</property>
<!-- 对于map属性的注入 -->
<property name="map">
<map>
<entry key="1" value="张三"></entry>
<entry key="2" value="李四"></entry>
<entry key="3" value="王五"></entry>
</map>
</property>
<!-- 对于List属性的注入 -->
<property name="list">
<list>
<value>假如给我三天光明</value>
<value>假易筋经</value>
<value>钢铁是怎样炼成的</value>
<value>三体</value>
</list>
</property>
<!-- 对于Set属性的注入 -->
<property name="sets">
<set>
<value>Mysql</value>
<value>Redis</value>
<value>Java</value>
<value>Java</value>
</set>
</property>
</bean>
</beans>
测试:
@Test
public void test(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean2.xml");
Library library = context.getBean("library", Library.class);
System.out.println(library);
}
结果:
Library{arrays=[1, 2, 3, 4, 5, 5], list=[假如给我三天光明, 假易筋经, 钢铁是怎样炼成的, 三体], map={1=张三, 2=李四, 3=王五}, sets=[Mysql, Redis, Java]}
2-集合对象注入
其实有点类似于普通的集合注入,区别主要是value和ref的更换,以及相关的bean的创建,value主要是针对普通数据类型,ref主要是引用数据类型(对象)。
类:
public class Course {
private String courseName;
public void setCourseName(String courseName) {
this.courseName = courseName;
}
@Override
public String toString() {
return "Course{" +
"courseName='" + courseName + '\'' +
'}';
}
}
public class CourseConnection {
private List<Course> courseList;
private Course[] courseArrays;
private Map<String,Course> map;
private Set<Course> sets;
public void setCourseList(List<Course> courseList) {
this.courseList = courseList;
}
public void setCourseArrays(Course[] courseArrays) {
this.courseArrays = courseArrays;
}
public void setMap(Map<String, Course> map) {
this.map = map;
}
public void setSets(Set<Course> sets) {
this.sets = sets;
}
@Override
public String toString() {
return "CourseList{" +
"courseList=" + courseList +
", \ncourseArrays=" + Arrays.toString(courseArrays) +
", \n map=" + map +
", \n sets=" + sets +
'}';
}
}
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 class="com.spring.entity.Course" id="course">
<property name="courseName" value="Spring5"></property>
</bean>
<bean class="com.spring.entity.Course" id="course2">
<property name="courseName" value="Mybatis"></property>
</bean>
<bean class="com.spring.entity.Course" id="course3">
<property name="courseName" value="SpringMVC"></property>
</bean>
<bean class="com.spring.entity.CourseConnection" id="courses">
<!-- List对象集合 -->
<property name="courseList">
<list>
<ref bean="course"></ref>
<ref bean="course2"></ref>
<ref bean="course3"></ref>
</list>
</property>
<!-- Array对象集合 -->
<property name="courseArrays">
<array>
<ref bean="course"></ref>
<ref bean="course2"></ref>
<ref bean="course3"></ref>
</array>
</property>
<!-- map对象集合 -->
<property name="map">
<map>
<entry key="1" value-ref="course"></entry>
<entry key="2" value-ref="course2"></entry>
<entry key="3" value-ref="course3"></entry>
</map>
</property>
<!-- set对象集合 -->
<property name="sets">
<set>
<ref bean="course"></ref>
<ref bean="course2"></ref>
<ref bean="course3"></ref>
<ref bean="course"></ref>
</set>
</property>
</bean>
</beans>
3-提取公共部分
提取公共部分,可以实现资源的共享,这里使用到了util标签。
实体类还是Librery类
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"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!--
把集合注入部分提取出来(即共享集合,脱离特有的对象)
-->
<util:list id="list">
<value>假如给我三天光明</value>
<value>假易筋经</value>
<value>钢铁是怎样炼成的</value>
<value>三体</value>
</util:list>
<util:map id="map">
<entry key="1" value="张三"></entry>
<entry key="2" value="李四"></entry>
<entry key="3" value="王五"></entry>
</util:map>
<util:set id="set">
<value>Mysql</value>
<value>Redis</value>
<value>Java</value>
<value>Java</value>
</util:set>
<!-- 对于注入集合属性的使用 -->
<bean class="com.spring.entity.Library" id="library">
<!-- 对于数组属性的注入 -->
<property name="arrays">
<array>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
<value>5</value>
<value>5</value>
</array>
</property>
<!-- 对于map属性的注入 -->
<property name="map" ref="map"></property>
<!-- 对于List属性的注入 -->
<property name="list" ref="list"></property>
<!-- 对于Set属性的注入 -->
<property name="sets" ref="set"></property>
</bean>
</beans>
测试:
@Test
public void test(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean3.xml");
Library library = context.getBean("library", Library.class);
System.out.println(library);
}
结果:
Library{arrays=[1, 2, 3, 4, 5, 5], list=[假如给我三天光明, 假易筋经, 钢铁是怎样炼成的, 三体], map={1=张三, 2=李四, 3=王五}, sets=[Mysql, Redis, Java]}
四、bean的作用域
实体类使用前面的Course类
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">
<!--
scope:
singleton:创建单实例
prototype:创建多实例(类似于克隆)
-->
<bean class="com.spring.entity.Course" id="course" scope="prototype"></bean>
</beans>
测试:
@Test
public void scopeTest(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean4.xml");
Course course = context.getBean("course", Course.class);
Course course1 = context.getBean("course", Course.class);
if(course==course1){ // hashCode
System.out.println("单实例");
}
else{
System.out.println("多实例");
}
}
结果:
多实例
写这个文章主要是用于自己对知识点的梳理,当然也有想让各位跟我一样的小白参考,作者学识浅薄,有可能有错误,所以欢迎纠错,一起学习讨论,一起进步。