spring就是一个java框架,使用java语言开发的, 轻量级的, 开源的框架。 可以在j2se、j2ee项目中都可以使用。
spring核心技术: ioc, aop
spring又叫做:容器, spring作为容器, 装的是java对象。 可以让spring创建java对象, 给属性赋值。
spring作用: 实现解耦合, 解决java对象之间的耦合, 解决模块之间的耦合。
tomcat也是容器:管理的是servlet, listener, filter等对象。
创建HelloServlet 类, 写web.xml
spring:创建SomeServiceImpl, 写spring的配置文件。
https://spring.io
Spring 是一个框架,是一个半成品的软件。有 20 个模块组成。它是一个容器管理对象,容器是装东西的,Spring 容器不装文本,数字。装的是对象。Spring 是存储对象的容器。
(1) 轻量
Spring 框架使用的 jar 都比较小,一般在 1M 以下或者几百 kb。Spring核心功能的所需的 jar 总共在 3M 左右。
Spring 框架运行占用的资源少,运行效率高。不依赖其他 jar
(2) 针对接口编程,解耦合
Spring 提供了 Ioc 控制反转,由容器管理对象,对象的依赖关系。原来在程序代码中的对象创建方式,现在由容器完成。对象之间的依赖解耦合。
(3) AOP 编程的支持
通过 Spring 提供的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松应付在 Spring 中,开发人员可以从繁杂的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
(4) 方便集成各种优秀框架
Spring 不排斥各种优秀的开源框架,相反 Spring 可以降低各种框架的使用难度,Spring 提供了对各种优秀框架(如 Struts,Hibernate、MyBatis)等的直接支持。简化框架的使用。Spring 像插线板一样,其他框架是插头,可以容易的组合到一起。需要使用哪个框架,就把这个插头放入插线板。不需要可以轻易的移除。
IoC,Inversion of Control : 控制反转, 是一个理论,一个指导思想。 指导开发人员如何使用对象,管理对象的。 把对象的创建,属性赋值,对象的声明周期都交给代码之外的容器管理。
控制: 对象创建,属性赋值, 对象声明周期管理
反转:把开发人员管理对象的权限转移给了代码之外的容器实现。 由容器完成对象的管理。
正转:开发人员在代码中, 使用 new 构造方法创建对象。 开发人员掌握了对象的创建,属性赋值,对象从开始到销毁的全部过程。 开发人员有对 对象 全部控制。
通过容器,可以使用容器中的对象(容器已经创建了对象, 对象属性赋值了, 对象也组装好了)。
Spring就是一个容器,可以管理对象,创建对象,给属性赋值。
IoC的技术实现
DI ( 依赖注入) :Dependency Injection, 缩写是DI . 是IoC的一种技术实现。 程序只需要提供要使用的对象的名称就可以了, 对象如何创建, 如何从容器中查找,获取都由容器内部自己实现。
依赖名词: 比如说ClassA类使用了ClassB的属性或者方法,叫做ClassA依赖ClassB.
public class ClassB{
public void createOrder(){}
}
public class ClassA{
//属性
private ClassB b = new ClassB();
public void buy(){
b.createOrder();
}
}
执行ClassA的buy()
ClassA a = new ClassA();
a.buy();
Spring框架使用的DI实现IoC.
通过spring框架, 只需要提供要使用的对象名词就可以了。 从容器中获取名称对应的对象。
spring底层使用的 反射机制, 通过反射创建对象,给属性。
<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">
beans>
spring标准的配置文件:
1)根标签是 beans
2)beans 后面的是约束文件说明
3)beans里面是bean声明。
4)什么是bean:bean就是对象,spring容器管理的java对象,叫做bean。
1.容器对象ApplicationContext:接口
通过ApplicationContext对象,获取要使用的其他java对象,执行getBean(“的id”)
src/main/resources/beans.xml (熟练掌握后用其他的名字)
<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 id="someService" class="com.sunny.service.impl.SomeServiceImpl"/>
<bean id="someService1" class="com.sunny.service.impl.SomeServiceImpl"/>
<bean id="otherService" class="com.sunny.service.impl.OtherService"/>
<bean id="mydate" class="java.util.Date"/>
beans>
改变传统思想,要从容器中拿对象去用。
/*
* 获取容器中对象的信息
*
* */
@Test
public void test04(){
String config = "beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
// 获取容器中定义的对象的数量
int nums = ctx.getBeanDefinitionCount();
System.out.println("容器中定义对象的数量=="+nums);
// 获取容器中定义的对象名称
String names[] = ctx.getBeanDefinitionNames();
for (String name:names){
System.out.println("容器中对象的名称 ==="+name);
}
}
/*
* 让spring创建非自定义的对象
* 有class就能让spring创建对象
* */
@Test
public void test05(){
String config = "beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
Date date = (Date) ctx.getBean("mydate");
System.out.println("date==="+date);
OtherService service = (OtherService) ctx.getBean("otherService");
service.doOther();
}
Spring调用类的无参数构造方法,创建对象。对象创建后给属性赋值。
给属性赋值可以使用1)xml配置文件的标签和属性;2)使用注解。
DI的分类:1.set注入,也叫做设值注入;2.构造注入。
在xml配置文件中使用标签和属性,完成对象的创建,属性赋值。
概念:spring调用类中的set方法,在set方法中可以完成属性的赋值。推荐使用 applicationContext.xml
简单类型的设值注入,使用value
<bean id="mySchool" class="com.sunny.ba02.School">
<property name="name" value="北京大学"/>
<property name="address" value="北京的海淀区"/>
bean>
DI:给属性赋值
简单类型:java中的基本数据类型和String
1.set注入:spring调用类的set方法,通过set方法完成属性赋值
简单类型的set注入:
语法: <bean id="xxx" class="yyy">
<property name = "属性名" value="简单类型属性值"/>
....
bean>
2.set注入:
引用类型的set注入:
语法:<bean id="xxx" class="yyy">
<property name="属性名" ref="bean的id"/>
...
bean>
建议使用name的方式,可读性更高。
<bean id="myStudent" class="com.sunny.ba02.Student">
<property name="name" value="李四"/>
<property name="age" value="20"/>
<property name="email" value="[email protected]"/>
<property name="school" ref="mySchool"/>
bean>
构造注入:spring调用类中的有参数构造方法,在创建对象的同时,给属性赋值
构造注入,使用index
<bean id="myStudent2" class="com.sunny.ba03.Student">
<constructor-arg index="0" value="张三"/>
<constructor-arg index="1" value="26"/>
<constructor-arg index="2" ref="mySchool"/>
bean>
<bean id="myStudent3" class="com.sunny.ba03.Student">
<constructor-arg value="张峰"/>
<constructor-arg value="28"/>
<constructor-arg ref="mySchool"/>
bean>
<bean id="mySchool" class="com.sunny.ba03.School">
<property name="name" value="北京大学"/>
<property name="address" value="北京的海淀区"/>
bean>
创建文件对象
<bean id="myFile" class="java.io.File">
<constructor-arg name="parent" value="E:\\demo"/>
<constructor-arg name="child" value="SpringFile.txt"/>
bean>
public class MyTest03 {
@Test
public void test01(){
String config ="ba03/applicationContext.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
Student student =(Student) ctx.getBean("myStudent3");
System.out.println("student=="+student);
//获取File对象
File file = (File) ctx.getBean("myFile");
System.out.println("file==="+file.getName());
}
}
概念:spring可以根据某些规则给引用类型完成赋值。只对引用类型有效。规则byName,byType。
①:byName(按名称注入):java类中引用类型属性名称和Spring容器中bean的id名称一样的,且数据类型也是一样的,这些bean能够赋值给引用类型。
<bean id="myStudent" class="com.sunny.ba04.Student" autowire="byName">
<property name="name" value="李四"/>
<property name="age" value="20"/>
<property name="email" value="[email protected]"/>
bean>
<bean id="school" class="com.sunny.ba04.School">
<property name="name" value="清华大学"/>
<property name="address" value="北京的海淀区"/>
bean>
②:byType(按类型注入):java类中引用类型的数据类型和Spring容器中bean的class值是同源关系的,这样的bean赋值给引用类型。
2.byType(按类型注入):java类中引用类型的数据类型和bean的class是同源的。
这些bean能够赋值给引用类型。
同源关系:
1.java中引用类型的数据类型和bean的class值是一样的。
2.java中引用类型的数据类型和bean的class值是父子类关系的。
3.java中引用类型的数据类型和bean的class值是接口和实现类关系的。
语法:
<bean id="xxx" class="yy" autowire="byType">
简单类型属性赋值
bean>
注意:在xml配置文件中,符合条件的对象,只能有一个。
多于一个会报错
-->
<bean id="myStudent" class="com.sunny.ba05.Student" autowire="byType">
<property name="name" value="张三"/>
<property name="age" value="26"/>
<property name="email" value="[email protected]"/>
bean>
<bean id="primarySchool" class="com.sunny.ba05.PrimarySchool">
<property name="name" value="北京大兴小学"/>
<property name="address" value="北京大兴区"/>
bean>
需求:模拟一用户注册操作。
需要定义一个dao接口(UserDao)接口中的方法 insertUser(SysUser user ) , 定义接口的实现类 MySqlUserDao
inserUser()方法里面不需要操作数据, 输出“使用了dao执行insert操作”。
需要定义一个service接口(UserService),定义接口的实现类 UserServiceImpl. 在service的实现类有一个 UserDao类型的属性。 service类中有一个方法 addUser(SysUser user).
操作是 service类中的addUser() { userDao.insertUser() } 完成注册。
定义一个实体类 SysUser, 表示用户的数据。
要求实现:
程序中的UserServiceImpl, MySqlUserDao这些类都有spring容器创建和管理, 同时要给 UserServiceImpl类中的 userDao属性赋值。 从spring容器中获取 UserServiceImpl类型的对象, 调用addUser()方法,输出“使用了dao执行insert操作”。
<bean id="sysuser" class="com.login.entity.SysUser" >
<property name="username" value="admin"/>
<property name="password" value="123456"/>
bean>
<bean id="userDao" class="com.login.dao.Imp.MySqlUserDao"/>
<bean id="userService" class="com.login.service.Imp.UserServiceImpl">
<property name="userDao" ref="userDao"/>
bean>
@Test
public void test01(){
String config ="dao/applicationContext.xml";
ApplicationContext cxt = new ClassPathXmlApplicationContext(config);
SysUser user = (SysUser) cxt.getBean("sysuser");
UserServiceImpl userService =(UserServiceImpl) cxt.getBean("userService");
userService.addUser(user);
}
分多个配置文件的方式
①按功能模块分,一个模块一个配置文件。
②按类的功能分,数据库操作相关的类在一个文件,service类在一个配置文件,配置redis,事务等等的一个配置文件。
Spring管理多个配置文件,常用的是包含关系的配置文件、项目中有一个总的文件,里面有import标签包含其他多个配置文件。
语法:
总的文件
<import resource="其他的文件的路径1"/>
<import resource="其他的文件的路径2"/>
关键字“classpath”:表示类路径,也就是类文件(class文件)所在的目录。Spring到类路径中加载文件什么时候使用 classpath:在一个文件中要使用其他的文件,需要使用classpath。
<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">
<import resource="classpath:ba06/spring-school.xml"/>
<import resource="classpath:ba06/spring-student.xml"/>
<import resource="classpath:ba06/spring-*.xml"/>
beans>
基于注解的DI:使用spring提供的注解,完成java对象的创建,属性赋值。
1.在源代码加入注解,例如@Component。
2.在Spring的配置文件,加入组件扫描器的标签。
<context:component-scan base-package="注解所在的包名"/>
1.创建对象的注解
@Component 普通jiava对象
@Respository dao对象,持久层对象,表示对象能访问数据库。
@Service service对象,业务层对象,处理业务逻辑,具有事务能力。
@Controller 控制器对象,接受请求,显示请求处理的结果。
2.简单类型属性赋值
@Value
3.引用类型赋值
@Autowired:spring提供的注解,支持byName,byType
@Autowired:默认就是byType
@Autowired @Qualifier:使用byName
@Resource:来自jdk中的注解,给引用类型赋值的,默认是byName
@Resource:先使用byName,在byType
@Resource(name=“bean的名称”):只使用byName注入。
/**
* @Component: 表示创建对象,对象放到容器中。作用是
* 属性:value,表示对象名称,也就是bean的id属性值
* 位置:在类的上面,表示创建子类的对象。
*@Component(value = "myStudent")等同于
*
*
* 和@Component功能相同的创建对象的注解。
* 1)@Repository:放在dao接口的实现类上面,表示创建dao对象,持久层对象。能访问数据库
* 2)@Service :放在业务层接口的实现类上面,表示创建业务层对象,业务层对象有事务的功能。
* 3)@Controller:放在控制器类上面,表示创建控制器对象。属于表示层对象。
* 控制器对象能接受请求,把请求的处理结果显示给用户。
* 以上四个注解都能创建对象,但是@Repository @Service @Controller有角色说明,表示对象是分层的。
* 对象是属于不同层的,具有额外的功能。
* */
//使用value 指定对象的名称。
//@Component(value = "myStudent")
//省略value
@Component("myStudent")
// 没有提供自定义对象名称,使用框架的默认独享名称:类名首字母小写。
//@Component
public class Student {
<context:component-scan base-package="com.sunny.ba01"/>
<context:component-scan base-package="com.sunny.ba01"/>
<context:component-scan base-package="com.sunny.ba02"/>
<context:component-scan base-package="com.sunny.ba01;com.sunny.ba02"/>
<context:component-scan base-package="com.sunny"/>
这个只是基本的使用格式,还可以外部提供值。
/*
* 简单类型的属性赋值:@value
* @Value :简单类型属性赋值
* 属性:value 简单类型属性值
* 位置:1)在属性定义的上面,无需set方法,推荐使用。
* 2)在set方法的上面
* */
@Value(value = "李四")
private String name;
private int age;
public Student(){
System.out.println("Student 无参数构造方法");
}
public void setName(String name) {
this.name = name;
}
@Value(value = "20")
public void setAge(int age) {
System.out.println("setAge===="+age);
this.age = age;
}
resources文件下新建 myconf.properties。在applicationContext.xml文件中配置。
<context:property-placeholder location="classpath:/myconf.properties"/>
@Value("${myname}")
@Value(value = "${myage}")
/**
* 引用类型
* @Autowired: spring框架提供的,给引用类型赋值的,使用自动注入原理。
* 支持byName,byType。默认是byType。
* 位置:1)在属性定义的上面,无需set方法,推荐使用
* 2)在set方法上面
* */
//默认使用byType
@Autowired
private School school;
/*
* byName自动注入:
* 1)@Autowired:给引用类型赋值
* 2)@Qualifer(value="bean的id"):从容器中找到指定名称的对象,
* 把这个对象赋值给引用类型。
* */
//byName
@Autowired
@Qualifier(value = "myschool")
private School school;
推荐用true @Autowired
* 属性:required:boolean类型的属性,默认为true
* true:spring在启动的时候,创建容器对象的时候,会检查引用类型是否赋值成功。
* 如果赋值失败,终止程序执行,并报错。
* false:引用类型赋值失败,程序正常执行,不报错。引用类型的值是null
//byName
@Autowired(required = false)
@Qualifier(value = "myschoolaaa")
private School school;
/**
* 引用类型
* @Resource: 来自jdk中,给引用类型赋值的,支持byName,byType,默认是byName
* Spring框架支持这个注解的使用。
* 位置:1)在属性定义的上面,无需set方法,推荐使用
* 2)在set方法的上面。
* 说明,使用jdk1.8带有@Resource注解,高于jdk1.8没有这个@Resource,需要加一个依赖。
*
* javax.annotation
* javax.annotation-api
* 1.3.2
*
* */
//默认byName自动注入
//先使用byName赋值,如果赋值失败,再使用byType.
//本例是byType赋值成功
@Resource
private School school;
//只用byName自动注入
@Resource(name = "mySchool")
private School school;
loC:管理对象的,把对象放在容器中,创建,赋值,管理依赖关系。
loC:通过管理对象,实现解耦合。loC解决处理业务逻辑对象之间的耦合关系,也就是service和dao之间的解耦合。
spring作为容器适合管理什么对象:
1)service对象,dao对象。
2)工具类对象
不适合交给spring的对象?
1)实体类。比如动态的对象,用户输入的信息创建的对象,mybatis查出来的对象。
2)servlet,listener,filter等web中的对象。他们是tomcat创建和管理的。