Spring框架[一]——spring概念和ioc入门(ioc操作xml配置文件)
Spring概念
- spring是开源的轻量级框架(即不需要依赖其他东西,可用直接使用)
spring核心主要两部分
- aop:面向切面编程,扩展功能不是修改源代码来实现;
- ioc:控制反转,比如:有一个类,在类中有个方法(非静态的方法),要调用类中的这个方法,则需要创建类的对象,使用对象调用方法。创建类对象的过程,需要new出来对象;而ioc则是将对象的创建不是通过new方式实现,而是交给spring配置来创建对象(即,将对象的创建交给spring来管理);
spring是一站式框架
- spring在javaee三层结构中,每一层都提供不同的解决技术
- web层:springMVC
- service层:spring的ioc
- dao层:spring的jdbcTemplate
spring版本
- hibernate5.x
- spring4.x
Spring入门
Spring的ioc操作
- 即:把对象的创建交给spring进行管理
- ioc两种操作方式:
- ioc的配置文件方式;
- ioc的注解方式;
IOC底层原理
- ioc底层原理使用的技术
- xml配置文件
- dome4j解析xml
- 工厂设计模式
- 反射
- 画图分析ioc实现原理
IOC入门案例
- 步骤:
- 导入jar包;
- 解压下载的spring-framework-4.2.4.RELEASE.zip文件,jar包特点:都有三个jar包(基本jar、文档jar、源码jar);
- 做spring基本功能,只需导入四个核心点jar包即可(Beans、core、Context、SpEL);
- 导入支持日志输出的jar包-logging、log4j(因为spring本身没有提供这种jar包);
- 解压下载的spring-framework-4.2.4.RELEASE.zip文件,jar包特点:都有三个jar包(基本jar、文档jar、源码jar);
- 创建类,在类中创建方法;
package cn.cbb.ioc; public class User { public void add() { System.out.println("add ..."); } public static void main(String[] args) { /** * 调用类中的方法,原始做法是创建类对象,用对象调用方法;而现在则不再这样做了, * 而是将对象的创建过程交给spring来配置实现,但是底层用的肯定是反射,我们不需 * 要写反射代码,由spring代我们做此操作 */ User user = new User(); user.add(); } }
- 创建spring配置文件,配置创建类;
- spring核心配置文件名称和位置不是固定的,建议放在src下面,官方建议applicationContext.xml
- 引入schema约束
- 配置对象创建,配置如下:
<?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"> <!-- ioc入门,配置对象的创建 --> <bean id="user" class="cn.cbb.ioc.User"></bean> </beans>
- 写代码测试对象创建:
package cn.cbb.ioc; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class IOCTest { @Test public void IOCTest() { //1、加载spring配置文件,根据配置创建对象 ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); //2、得到配置创建的对象 User user = (User) context.getBean("user"); System.out.println(user); user.add(); } }
- 导入jar包;
配置文件无提示问题
Spring引入schema约束,把约束文件引入到eclipse中,以便配置文件编写提示:
spring的bean管理(xml配置文件)
bean实例化三种方式
- bean实例化,即:在spring里面通过配置文件创建对象;
- bean实例化的三种方式实现(掌握一种,其他两种知道即可):
- 无参构造函数创建(重点🌟🌟🌟)
<!-- ioc入门,配置对象的创建 --> <bean id="user" class="cn.cbb.ioc.User"></bean>
对象对应的类中,若没有无参构造(定义了有参构造),则将出现异常:
org.springframework.beans.factory.BeanCreationException:...No default constructor found;...
- 静态工厂创建
通过工厂创建的静态方法来返回类对象(如:IOC底层原理图析中工厂类UserFactory创建的静态方法getService)
<!-- 使用静态工厂创建对象 --> <bean id="bean2Factory" class="cn.cbb.bean.Bean2Factory" factory-method="getBean2"></bean>
package cn.cbb.bean; public class Bean2Factory { //静态方法返回Bean2对象 public static Bean2 getBean2() { return new Bean2(); } }
- 实例工厂创建
通过工厂的非静态方法来返回对象
<!-- 使用实例工厂创建对象 --> <!-- 首先,创建工厂对象 --> <bean id="bean3Factory" class="cn.cbb.bean.Bean3Factory"></bean> <!-- 其次,通过实例化的工厂对象的方法来创建对象bean3 --> <bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean>
package cn.cbb.bean; public class Bean3Factory { //普通方法返回Bean3对象 public Bean3 getBean3() { return new Bean3(); } }
- 无参构造函数创建(重点🌟🌟🌟)
bean标签常用属性
- id属性:命名,可任意命名。
- id属性值,不能包含特殊符号;
- spring是根据id值找到配置对象;
- class属性:创建对象所在类的全路径
- name属性:功能和id属性一致,都可以找到配置对象(主要区别:name可以包含特殊符号);现在用的较少,主要是为了整合strus1那种框架而遗留下来的一个属性。
- scope属性:
User user1 = (User) context.getBean("user"); User user2 = (User) context.getBean("user"); System.out.println(user1); System.out.println(user2);
- singleton:默认值,单例
<!-- 默认scope="singleton" --> <bean id="user" class="cn.cbb.ioc.User"></bean>
cn.cbb.ioc.User@b7dd107 cn.cbb.ioc.User@b7dd107
- prototype:多例
<!-- scope="prototype"测试 --> <bean id="user" class="cn.cbb.ioc.User" scope="prototype"></bean>
cn.cbb.ioc.User@b7dd107 cn.cbb.ioc.User@42eca56e
- singleton:默认值,单例
属性注入方式介绍
- 属性注入:创建对象时,为对象的属性设置值
- 注入方式介绍(三种)
- 属性的setXXX方法注入
- 有参构造注入
- 接口注入
spring注入基本类型属性(仅支持前两种方式:有参构造和set方法)
- set方式注入(最常用)
<!-- 使用set方法注入属性 --> <bean id="book" class="cn.cbb.property.Book"> <!-- 注入属性之: name属性值:类中的属性名称; value属性:设置的具体值 --> <property name="bookName" value="红楼梦"></property> </bean>
package cn.cbb.property; public class Book { private String bookName; //set方法 public void setBookName(String bookName) { this.bookName = bookName; } public void testBook() { System.out.println("bookName通过set注入值为:"+bookName); } }
- 有参构造注入
<!-- 使用有参数构造注入属性 --> <bean id="propertyDemo1" class="cn.cbb.property.PropertyDemo1"> <constructor-arg name="userName" value="小码"></constructor-arg> </bean>
package cn.cbb.property; public class PropertyDemo1 { private String userName; public PropertyDemo1(String userName) { this.userName = userName; } public void test1() { System.out.println("userName通过有参构造注入值为:"+userName); } }
spring注入对象类型属性(重点)
- 首先,准备service类和dao类
- 其次,要在service中得到dao对象,具体实现:
- 在service中把dao作为类型属性
- 生成dao类型属性的set方法
package cn.cbb.ioc; public class UserService { //定义dao类型属性 private UserDao userDao; //生成set方法,在service中得到dao对象,就可以调用dao中的方法 public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void add() { System.out.println("service add ..."); userDao.add(); } }
- 配置文件关系
<!-- 注入对象类型的属性 --> <!-- 配置service和dao对象 --> <bean id="userDao" class="cn.cbb.ioc.UserDao"></bean> <bean id="userService" class="cn.cbb.ioc.UserService"> <!-- 注入dao对象: name属性值:service中的属性名称,对象类型属性就不要写value了,用ref属性:dao配置bean的id值 --> <property name="userDao" ref="userDao"></property> </bean>
P命名空间注入(不常用,了解即可)
package cn.cbb.property; public class Person { private String pname; public void setPname(String pname) { this.pname = pname; } public void testP() { System.out.println("P名称空间注入pname值为"+pname); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" 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"> <!-- P名称空间注入 --> <bean id="person" class="cn.cbb.property.Person" p:pname="小张"></bean> </beans>
spring注入复杂数据
- 数组
- list集合
- map集合
- properties类型(键值对文件)
package cn.cbb.property; import java.util.List; import java.util.Map; import java.util.Properties; public class Animal { private String[] arrs; private List<String> list; private Map<String,String> map; private Properties properties; public void setArrs(String[] arrs) { this.arrs = arrs; } public void setList(List<String> list) { this.list = list; } public void setMap(Map<String, String> map) { this.map = map; } public void setProperties(Properties properties) { this.properties = properties; } public void testAnimal() { System.out.println("复杂数据注入arrs:"+arrs); System.out.println("复杂数据注入list:"+list); System.out.println("复杂数据注入map:"+map); System.out.println("复杂数据注入properties:"+properties); } }
<!-- 注入复杂类型属性值 --> <bean id="animal" class="cn.cbb.property.Animal"> <!-- 数组 --> <property name="arrs"> <list> <value>小王</value> <value>小李</value> <value>小张</value> </list> </property> <!-- list --> <property name="list"> <list> <value>奥迪</value> <value>宝马</value> <value>奔驰</value> </list> </property> <!-- map --> <property name="map"> <map> <entry key="aa" value="lucy"></entry> <entry key="bb" value="lili"></entry> <entry key="cc" value="tom"></entry> </map> </property> <!-- properties --> <property name="properties"> <props> <prop key="driverclass">com.mysql.jdbc.Driver</prop> <prop key="username">root</prop> </props> </property> </bean>
IOC和DI区别
- IOC:控制反转,把对象的创建交给spring进行配置管理;
- DI:依赖注入,向类中属性中设置值;
- 关系:依赖注入不能单独存在,需要在IOC的基础之上铼完成操作。
spring整合web项目原理✨✨✨
- 加载spring核心配置文件
//1、加载spring配置文件,根据配置创建对象 ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
new对象,功能可以实现,但是效率太低!
- 解决思路:把加载配置文件和创建对象的过程,放在服务器启动的时候来完成。
- 实现原理:
- ServletContext对象(服务器启动后,项目中唯一一个对象)
- 监听器(监听ServletContext对象在什么时候创建)
- 具体使用:
- 在服务器启动的时候,为每个项目创建一个ServletContext对象;
- 使用监听器监听ServletContext对象创建时间;
- 监听到ServletContext对象创建的时候,加载spring配置文件,然后把配置文件配置的对象进行创建;
- 把创建出来的对象放到ServletContext域对象中(setAttribute方法)
- 获取对象时,到ServletContext域中通过getAttribute方法获取;