今天学完了Spring5,还是感觉迷迷糊糊的,对其中的一些操作记忆还不是很劳,今天开始复习Spring5,巩固一下记忆。

首先在学完了Spring5之后,这个框架给我的感觉就是创建对象更加方便了,我们可以通过注解或者配置文件的方式进行对象的注入,不用再自己手动创建了。

其中还有JDBC的新操作以及事务管理,大大简化了我们的代码,让我们的代码更加清新。

首先Spring5运用了IOC(控制反转)编程思想(也叫依赖注入),那么什么是IOC编程思想呢?



我们都知道在面向对象的软件设计中,它的底层都是由N个对象构成,各个对象之间通过相互合作,最终实现系统地业务逻辑。
但是在庞大的软件体系中对象的依赖关系越来越复杂,耦合度越来越高,很有可能“牵一发而动全身”,因此,Michael Mattson提出了IOC理论。

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


Spring5---复习笔记1_属性注入

我们再来看看,控制反转(IOC)到底为什么要起这么个名字?我们来对比一下:

软件系统在没有引入IOC容器之前,如图1所示,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。

软件系统在引入IOC容器之后,这种情形就完全改变了,如图3所示,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。   

通过前后的对比,我们不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。

 

IOC这个东西好像就是可以利用配置文件进行对象的创建,那么如何用代码实现呢?

使用我们要引入Spring的jar包,可以用Maven,也可以去官网下载:

Spring5---复习笔记1_创建对象_02需要使用的jar包

接着就可以使用IOC进行bean管理操作了,bean管理:



(1) Spring创建对象
(2) Spring注入属性


我们可以在配置文件中进行对象的创建以及向这个对象中注入属性。

1、基于XML创建对象

我们首先创建User(Bean)类:



public class User {

private String username;

public void add()
{
System.out.println("add.........");
}

}


接着就可以在xml文件中利用bean标签创建对象了,

 在idea的src下创建Spring.xml文件后:



<!--配置User对象创建-->
<bean id="user" class="com.spring5.User"></bean>


对象就创建在IOC容器中了,这感觉好像有点虚幻,我们可以测试一下。

在java程序中:



@Test
public void testUser(){
//1.加载spring的配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
//2.获取配置创建的对象
User user = context.getBean("user", User.class);

user.add();
System.out.println(user);
}


运行后控制台输出:



add.........
com.spring5.User@16f7c8c1


这说明我们的对象确实创建出来了。

2、基于xml注入基本属性



DI:依赖注入,注入属性
第一种注入方式 : set方法注入
(1) 创建一个类,定义属性的对应的set方法 见spring5中的 Book类
(2) 在spring配置文件中配置对象的创建,再配置属性的注入
bean内使用property完成属性注入
name:属性名称
value:属性注入的值
第二种注入方式 : 构造函数注入
(1) 创建一个类,定义属性和有参构造 见spring5中的 Orders类
(2) 在spring配置文件中配置对象的创建,以及构造器参数的导入
bean内使用 constructor-arg 完成属性注入
name:属性名称
value:属性注入的值


Bean类:



public class Book {
//创建属性
private String bname;
private String bauthor;
private String address;

//set方法注入
public void setBname(String bname) {
this.bname = bname;
}

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

public void setBauthor(String bauthor) {
this.bauthor = bauthor;
}

@Override
public String toString() {
return "Book{" +
"bname='" + bname + '\'' +
", bauthor='" + bauthor + '\'' +
", address='" + address + '\'' +
'}';
}
}


xml配置文件(基于set方法):



<!--创建对象-->
<bean id="book" class="com.spring5.Book">
<!--bean内使用property完成属性注入
name:属性名称
value:属性注入的值
-->
<property name="bname" value="易筋经"> </property>
<property name="bauthor" value="达摩老祖"> </property>
<!--null值-->
<!-- <property name="address">-->
<!-- <null/>-->
<!-- </property>-->
<!--属性值中包含特殊符号
1、<>进行转义 << >>
2、把带特殊符号内容写到CDATA中
-->
<property name="address">
<value><![CDATA[<<南京>>]]></value>
</property>
</bean>


java程序:



@Test
public void testBook1() {
//1.加载spring的配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
//2.获取配置创建的对象
Book book = context.getBean("book", Book.class);

System.out.println(book);
}


控制台输出:



Book{bname='易筋经', bauthor='达摩老祖', address='<<南京>>'}


我们可以看到属性确实被注入进对象了。

 

xml配置文件(基于构造器):

Order(Bean)类:



public class Orders {

private String oname;

private String address;

public Orders(String oname, String address) {
this.oname = oname;
this.address = address;
}

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


注意这里没有空构造器,所以当我们在xml文件中直接创建对象(空)时会报错

xml配置文件(构造器):



<bean id="order" class="com.spring5.Orders">
<constructor-arg name="oname" value="computer"> </constructor-arg>
<constructor-arg name="address" value="cn"> </constructor-arg>
</bean>


java程序:



@Test
public void testOrder1()
{
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");

Orders order = context.getBean("order", Orders.class);

System.out.println(order);
}


控制台输出:



Orders{oname='computer', address='cn'}


 

简化:我们可以在xml配置文件中通过p命名空间简化set注入属性操作(不过这个操作我倒是不经常用,property其实是我最喜欢用的方式):

首先在beans标签中添加xmlns:p属性:



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


接着配置bean对象:



<!--创建对象-->
<bean id="book1" class="com.spring5.Book" p:bname="九阳神功" p:bauthor="无名氏">
<!--bean内使用property完成属性注入
name:属性名称
value:属性注入的值
-->
</bean>


java程序:



@Test
public void testBook2() {
//1.加载spring的配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
//2.获取配置创建的对象
Book book = context.getBean("book1", Book.class);

System.out.println(book);
}


控制台输出:



Book{bname='九阳神功', bauthor='无名氏', address='null'}


 

 

3、基于xml注入外部bean属性

UserDao接口以及UserDaoImpl类以及UserService类:



public interface UserDao {
public void update();
}



public class UserDaoImpl implements UserDao {
@Override
public void update() {
System.out.println("Dao update......");
}
}



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配置:



<!--Service和Dao对象创建-->
<bean id="userService" class="com.service.UserService">
<!--注入userDao对象
ref属性:创建userDao对象bean标签id值
-->
<property name="userDao" ref="userDao"> </property>
</bean>
<bean id="userDao" class="com.dao.UserDaoImpl"> </bean>


我们在property标签中添加ref属性,属性值是外部bean对象的id

java程序:



@Test
public void testUserService(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}


控制台输出:



service add......
Dao update......


 

4、基于xml设置内部Bean属性:

Employee类以及Department类(Bean):



public class Department {

private String dname;


public void setDname(String dname) {
this.dname = dname;
}

@Override
public String toString() {
return "Department{" +
"dname='" + dname + '\'' +
'}';
}
}



public class Employee {
private String ename;
private String gender;
//员工所属的部门
private Department department;

public void setDepartment(Department department) {
this.department = department;
}

public void setEname(String ename) {
this.ename = ename;
}

public void setGender(String gender) {
this.gender = gender;
}

public Department getDepartment() {
return department;
}

@Override
public String toString() {
return "Employee{" +
"ename='" + ename + '\'' +
", gender='" + gender + '\'' +
", department=" + department +
'}';
}
}


web.xml配置:



<!--内部bean-->
<bean id="emp" class="com.bean.Employee">
<property name="ename" value="张三"> </property>
<property name="gender" value="男"> </property>
<!--设置对象类型属性-->
<property name="department">
<bean id="dept" class="com.bean.Department">
<property name="dname" value="程序猿"> </property>
</bean>
</property>
</bean>


我们可以看到就是往property中添加对象

java程序:



@Test
public void testEmp(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
Employee emp = context.getBean("emp", Employee.class);
System.out.println(emp);
}


控制台输出:



Employee{ename='张三', gender='男', department=Department{dname='程序猿'}}


 

我们也可以通过级联赋值方式配置:

xml配置文件内容:



<!--级联赋值-->
<bean id="emp" class="com.bean.Employee">
<property name="ename" value="张三"> </property>
<property name="gender" value="男"> </property>

<!--级联赋值-->
<property name="department" ref="dept"> </property>
<!--需要在Employee类中实现dept的get方法-->
<property name="department.dname" value="技术部"> </property>
</bean>
<bean id="dept" class="com.bean.Department">
<property name="dname" value="财务部"> </property>
</bean>


我们首先利用外部bean创建对象,再利用级联赋值修改内部对象的属性值。

通过使用property属性,name是类中对象名称.属性名称,这要求均实现set方法。

最终输出:



Employee{ename='张三', gender='男', department=Department{dname='技术部'}}