Spring两大核心技术:IOC容器(控制反转)和依赖注入
控制反转(IoC:Inversion of Control)/依赖注入(DI:Dependency Injection)
面向切面编程(AOP:Aspect Oriented Programming)
IoC:即控制反转。举例来说:在之前的操作中,如果有一个类,我们想要调用类中的方法(不是静态方法),就要创建该类的
对象,使用对象调用方法来实现。但对于Spring来说,Spring创建对象的过程,不是在代码里面来实现的,而是交给Spring来
进行配置实现的。
IoC不是一种技术,只是一种思想,代码松耦合,结构灵活,很好的体现了面向对象的设计法则。
依赖注入(DI):在IOC容器创建完对象后,处理对象之间的依赖关系。
注入方式:1.set注入(案例中会使用) 2.构造注入 3.注解注入
AOP:即面向切面编程。
控制反转
含义:依赖容器给予你资源,控制权在容器身上,不主动new对象,而是哪里需要对象,便向容器发出请求,
让容器帮自己new一个对象
依赖注入
含义:所需求的对象,需要依赖容器注入。
核心容器提供Spring框架的基本功能实现,核心容器主要组件BeanFactory,它是工厂模式的实现。
BeanFactory使用控制反转(IOC)模式将应用程序配置和依赖于实际应用程序代码分开
概念
依赖注入(Dependency Injection,DI)
依赖:指Bean对象的创建依赖于容器,Bean对象的依赖资源。
注入:指Bean对象所依赖的资源,由容器 来设置和装配。
Set注入构造注入
通过setter访问器实现通过构造方法实现灵活性好,但是setter方法数量比较多灵活性差,仅靠重载限制太多时效性差时效性好通过无参构造实例化通过匹配的构造方法实例化,但建议保留无参构造
构造器注入
简单来说:构造器注入就是容器调用类的构造函数,来完成对象的初始化。就是使用构造方法来注入信息。此构造方法共有三个参数:userCode userName userPwd,分别属于Integer类型,String类型和类类型。
public class User {
private String userCode;
private String userName;
private String userPwd;
public User() {
}
public User(String userCode, String userName, String userPwd) {
this.userCode = userCode;
this.userName = userName;
this.userPwd = userPwd;
}
public String getUserCode() {
return userCode;
}
public void setUserCode(String userCode) {
this.userCode = userCode;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
}
配置Application文件 配置文件中会有指定参数的类型,指定参数的顺序,指定参数的名称。
<?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">
<!-- 构造函数注入 index:下标注入-->
<bean id="test_userA" class="org.westos.demo.entity.User">
<constructor-arg index="0" value="wangwu"></constructor-arg>
<constructor-arg index="1" value="王五"></constructor-arg>
<constructor-arg index="2" value="123456"></constructor-arg>
</bean>
<!-- 构造函数注入 index:名称注入-->
<bean id="test_userB" class="org.westos.demo.entity.User">
<constructor-arg name="userCode" value="wangwu"></constructor-arg>
<constructor-arg name="userName" value="王五"></constructor-arg>
<constructor-arg name="userPwd" value="123456"></constructor-arg>
</bean>
<!-- 构造函数注入 type:类型注入-->
<bean id="test_userC" class="org.westos.demo.entity.User">
<constructor-arg type="java.lang.String" value="wangwu"></constructor-arg>
<constructor-arg type="java.lang.String" value="王五"></constructor-arg>
<constructor-arg type="java.lang.String" value="123456"></constructor-arg>
</bean>
</beans>
测试类
public class TestUser {
@Test
public void testUser(){
@Test
public void testB(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
User userA = (User) applicationContext.getBean("test_userA");
User userB = (User) applicationContext.getBean("test_userB");
User userC = (User) applicationContext.getBean("test_userC");
User userD = (User) applicationContext.getBean("test_userD");
System.out.println(userA.getUserName()+"---"+userA.getUserCode()+"---"+userA.getUserPwd());
System.out.println(userB.getUserName()+"---"+userB.getUserCode()+"---"+userB.getUserPwd());
System.out.println(userC.getUserName()+"---"+userC.getUserCode()+"---"+userC.getUserPwd());
System.out.println(userD.getUserName()+"---"+userD.getUserCode()+"---"+userD.getUserPwd());
}
}
Set注入(重点)
接口类
public interface UserService {
//添加用户
int addUser(User user);
//修改用户
int updateUser(User user);
//删除用户
int deleteUser(String userID);
}
实现类
public class UserServiceImpl implements UserService {
private UserDao userDao;
// 创建SET访问器 用于spring 进行当前注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
Application.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">
<!--set注入:业务层需要dao层,因为需要将dao层的实现类注入业务层。
注入: 需要将userdao注入给UserServiceImpl p:来自当前类-ref-->
<bean id="userService" class="org.westos.demo.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
测试类
public class TestUser {
@Test
public void testUser(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
/*转换为 接口 接口 接口 UserService*/
UserService userService = (UserService) applicationContext.getBean("userService");
int row = userService.addUser(new User("admin", "张三", "123456"));
System.out.println(row==1?"成功":"失败");
}
}
Set注入实例
scop : 设置bean的作用域
singleton:默认值 在spirng IOC 容器仅存在一个bean ,单例模式
prototype: 每次从容器中调用Bean时 ,都返回一个新的实例 例如 new xxxBean();
request: 每次HTTP请求 都会创建一个新的Bean,作用域仅限于WEBApplicationContext环境
session:同一个HTTP Session共享一个Bean,不同的Session使用不同的Bean,作用域仅限于WEBApplicationContext环境
global-session:一般用于Portlet应用环境,作用域仅限于WEBApplicationContext环境
注入设置
//用于测试IOC 注入 不同的类型数据
public class TestEntity {
private String specialCharacter1; // 特殊字符值1
private String specialCharacter2; // 特殊字符值2
private User innerBean; // JavaBean类型
private List<String> list; // List类型
private String[] array; // 数组类型
private Set<String> set; // Set类型
private Map<String, String> map; // Map类型
private Properties props; // Properties类型
private String emptyValue; // 注入空字符串值
private String nullValue = "init value"; // 注入null值
public void setSpecialCharacter1(String specialCharacter1) {
this.specialCharacter1 = specialCharacter1;
}
public void setSpecialCharacter2(String specialCharacter2) {
this.specialCharacter2 = specialCharacter2;
}
public void setInnerBean(User user) {
this.innerBean = user;
}
public void setList(List<String> list) {
this.list = list;
}
public void setArray(String[] array) {
this.array = array;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProps(Properties props) {
this.props = props;
}
public void setEmptyValue(String emptyValue) {
this.emptyValue = emptyValue;
}
public void setNullValue(String nullValue) {
this.nullValue = nullValue;
}
public void showValue() {
System.out.println("特殊字符1:" + this.specialCharacter1);
System.out.println("特殊字符2:" + this.specialCharacter2);
System.out.println("内部Bean:" + this.innerBean.getUserName());
System.out.println("List属性:" + this.list);
System.out.println("数组属性[0]:" + this.array[0]);
System.out.println("Set属性:" + this.set);
System.out.println("Map属性:" + this.map);
System.out.println("Properties属性:" + this.props);
System.out.println("注入空字符串:[" + this.emptyValue + "]");
System.out.println("注入null值:" + this.nullValue);
}
}
常量注入
配置Application.xml文件(注入基本数据类型和String类型,注入包含特殊字符的字符串,内容定义Bean,List,数组,Set,Map,注入Properties类型,注入空字符串值,注入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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="testEntity" class="org.westos.demo.entity.TestEntity">
<!-- property : set注入-->
<!-- 注入包含特殊字符的 字符串 -->
<property name="specialCharacter1" >
<!-- <![CDATA[ 包含有特殊字符的字符串 ]]> -->
<value><![CDATA[&&]]></value>
</property>
<!-- 注入包含特殊字符的 字符串 -->
<property name="specialCharacter2">
<value>P&G</value>
</property>
<!-- 定义内部Bean -->
<property name="innerBean">
<bean class="org.westos.demo.entity.User" scope="singleton">
<property name="userCode" value="admin"></property>
<property name="userName" value="张三"></property>
<property name="userPwd" value="123456"></property>
</bean>
</property>
<!-- 注入List类型 -->
<property name="list">
<list>
<!-- 定义List中的元素 -->
<value>list_足球</value>
<value>list_篮球</value>
</list>
</property>
<!-- 注入数组类型 -->
<property name="array">
<list>
<!-- 定义数组中的元素 -->
<value>array_足球</value>
<value>array_篮球</value>
</list>
</property>
<!-- 注入Set类型 -->
<property name="set">
<set>
<!-- 定义Set或数组中的元素 -->
<value>set_足球</value>
<value>set_篮球</value>
</set>
</property>
<!-- 注入Map类型 -->
<property name="map">
<map>
<!-- 定义Map中的键值对 -->
<entry>
<key>
<value>football</value>
</key>
<value>足球</value>
</entry>
<entry>
<key>
<value>basketball</value>
</key>
<value>篮球</value>
</entry>
</map>
</property>
<!-- 注入Properties类型 -->
<property name="props">
<props>
<!-- 定义Properties中的键值对 -->
<prop key="football">props_足球</prop>
<prop key="basketball">props_篮球</prop>
</props>
</property>
<!-- 注入空字符串值 -->
<property name="emptyValue">
<value></value>
</property>
<!-- 注入null值 -->
<property name="nullValue">
<null/>
</property>
</bean>
</beans>
测试类
public class TestUser {
@Test
public void testA(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
TestEntity testEntity = (TestEntity) applicationContext.getBean("testEntity");
testEntity.showValue();
}
}
P命名空间注入
P 命名空间注入:在Application.xml 头部导入命名空间
xmlns:p="http://www.springframework.org/schema/p"
p 命名空间的特点:使用属性而不是子元素的形式配置Bean的属性,从而简化了配置代码
对于直接量(基本数据类型、字符串)属性:p:属性名="属性值"
对于引用Bean的属性:p:属性名-ref="Bean的id"
<!--p 命名空间的特点:使用属性而不是子元素的形式配置Bean的属性,从而简化了配置代码-->
<bean id="test_userD" class="org.westos.demo.entity.User" p:userCode="listi" p:userName="李四" p:userPwd="123456">
</bean>
<bean id="userService" class="org.westos.demo.service.impl.UserServiceImpl" p:userDao-ref="userDao">
</bean>
<bean id="userService" class="org.westos.demo.service.impl.UserServiceImpl" p:userDao-ref="userDao">
</bean>