1.spring概述
spring全家桶: spring, spring boot ,spring cloud,
spring:出现在2002左右,主要目的为了解决企业级开发的难度。减轻对项目块之间的管理,类和类之间的管理。帮助开发人员去创建对象,管理对象之间的关系。
? 核心技术: ioc控制反转,aop面向切面编程。 能够实现模块之间,类之间的解耦合。
依赖:class a中使用了class b 属性或者方法, 叫做class a 依赖 class b spring能管理a和b之间的关系
框架怎么学:框架是一个软件,其他人写好的软件。
1)知道框架能做什么,mybatis–访问数据库,对表中的数据执行增删改查。 2)框架的语法。框架要完成一个功能,需要一定的步骤支持的。 3) 框架的内部实现。框架内部怎么做。原理是什么。 4)通过学习可以,实现一个框架。
Spring 第一个核心功能 IoC
IoC(Inversion of Control) :控制反转。是一个理论,概念,思想。
描述的:把对象的创建,赋值。管理工作都交给代码之外的容器实现。也就是对象的创建是由其他外部资源完成。 控制:创建对象,对象的属性赋值、对象之间 的关系管理。
反转:把原来的开发人员管理,创建对象的权限转移给代码之外的容器来实现,由容器代替开发人员管理对象,创建对象。给属性赋值。
正转:有开发人员在代码中,使用new构造方法创建对象。开发人员主动管理对象。
容器:是一个服务器软件 也可以是一个框架。(spring)
依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.5</version>
</dependency>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<sorce>1.8</sorce>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
为什么要使用IoC :减少对代码的改动,也能实现不同的功能。 实现解耦合。
java中创建对象有哪些方式: ? 1.构造方法:new Student() ? 2.反射 ? 3.序列化 ? 4.克隆 ? 5.IoC ? 6.动态代理
IoC的体现:
servelet 1: 创建类继承HttpServelet
? 2: 在web.xml 注册servlet ,使用myservlet. ? com.sdyu.cont-controller.MyServlet 3. ? 没有创建过servlet对象,没有MyServlet myservlet - new MyServlet(); 4. ? Servlet 是Tomcat服务器它能你创建的。Tomcat 作为容器:里面存放的有Servlet对象,lisener,Filter对象。
IoC的技术实现:
? DI 是 IoC的技术实现。
? DI:依赖注入 只需要在程序中提供要使用的名称就可以了,至于这个对象如何在容器中创建
赋值、查找都由容器内部实现。
spring是使用的di实现了IoC的功能。spring底层创建,使用的是反射机制。
spring是一个容器,管理对象,给属性赋值,底层是由反射创建对象。
第一个例子 在resources中建立spring 的 头部解释: <?xml version="1.0" encoding="UTF-8"?>
? spring的配日志文件 ? 1.beans:是模板标签,spring把java对象成为beans ? 2.spring-beans.xsd 是约束文件,和mybatis指定 dtd是一样的
<!-- 告诉spring创建对象
声明bean,就是告诉spring要创建某个类的对象
id:对象的自定义名称,唯一值。spring通过这个名称找到对象
class:类的全限定名称(不能是接口,因为是spring是反射机制,必须使用类)
spring就完成 SomeService someService = new SomeServiceImpl();
spring 是把床号的对象放到map中,spring框架有一个map存放对象的
springMap.put(id的值,对象);
例如 springMap.put("someService",new SomeServiceImpl());
一个bean标签声明一个对象
-->
<bean id="someService" class="com.sdyu.service.Impl.SomeServiceImpl"/>
<!--
spring能创建一个非自定义的对象吗,创建一个存在的某个的对象。
-->
<bean id="mydate" class="java.util.Date"/>
新建resources 目录下的applictionContext.xml
简单类型的设值注入实现(setter)
<bean id="myStudent" class="com.sdyu.ba01.Student">
<property name="name" value="李四"/>
<property name="age" value="20"/>
</bean>
需要有set方法没有set方法是报错的
先创建对象,再调用set方法完成赋值
引用类型的设值注入实现
引用类型的set注入:spring 调用类的set方法
? <bean id ="" class="">
? <property name="属性名称" ref="bean的id(对象的名称)"/>
? </bean>
?
-->
<bean id="myStudent" class="com.sdyu.ba01.Student">
<property name="name" value="李四"/>
<property name="age" value="20"/>
<property name="school" ref="mySchool"/>
</bean>
<bean id ="mySchool" class="com.sdyu.ba01.School">
<property name="name" value="北京大学"/>
<property name="address" value="北京"/>
</bean>
须在Student类里面声明School对象
构造注入
spring调用类有参构造方法,在创建对象的同时,在构造方法中给属性赋值。 构造注入使用 标签:一个 表示构造方法一个参数。 标签属性: name:表示构造方法的形参名 index:表示构造方法的参数的位置,参数从左往右位置 0,1,2的顺序 value:构造方法的形参类型是简单类型的,使用value ref:构造方法的形参类型是引用类型的。使用ref
有参构造方法:
<bean id="mystudent2" class="com.sdyu.ba03.Student">
<constructor-arg index="0" value="张三"/>
<constructor-arg index="1" value="23"/>
<constructor-arg index="2" ref="mySchool"/>
</bean>
<bean id="mystudent3" class="com.sdyu.ba03.Student">
<constructor-arg value="张三"/>
<constructor-arg value="23"/>
<constructor-arg ref="mySchool"/>
</bean>
**构造注入创建文件对象**
<bean id="myfile" class="java.io.File">
<constructor-arg name="parent" value="C:\File\stsworkspace\ch4"/>
<constructor-arg name="child" value="readme.txt"/>
File myFile = (File) ac.getBean("myfile");
System.out.println(myFile.getName());
引用类型的自动注入
spring框架根据某些规则可以给引用类型赋值 不用你再赋值了 使用的规则常用的byName,byType. 1.byName(按名称注入):java类引用类型的属性名和spring容器中(配置文件)的id的名称一样。 且数据类型是一致的,这样的容器中的bean,spring能够赋值给引用类型。 语法:
<bean id="" class="" aotowire="">
简单类型属性赋值
</bean>
? 2.byType(按类型注入):java类中引用类型的数据类型和spring容器中(配置文件)的class属性 ? 是同源关系的,这样的bean能够赋值给引用类型 ? 同源就是一类的意思。: ? 1)java类中引用类型的数据类型和class的值是一样的。 ? 2)java类中引用类型的数据类型和class的值父子类关系的。 ? 3)java类中引用类型的数据类型和class的值接口和实现类关系的
注意:在byType中,在xml配置文件中声明bean只能有一个符合条件的, 多余一个是错误的
<bean id="" class="" autowire="byType">
简单类型属性赋值
</bean>
<bean id="myStudent" class="com.sdyu.ba04.Student" autowire="byName">
<property name="name" value="李四"/>
<property name="age" value="20"/>
</bean>
<bean id ="school" class="com.sdyu.ba04.School">
<property name="name" value="北京大学"/>
<property name="address" value="北京"/>
</bean>
第一种情况
<bean id="myStudent" class="com.sdyu.ba04.Student" autowire="byType">
<property name="name" value="李四"/>
<property name="age" value="20"/>
</bean>
第二种情况
<bean id="myStudent" class="com.sdyu.ba04.Student" autowire="byType">
<property name="name" value="李四"/>
<property name="age" value="20"/>
</bean>
<bean id="primarySchool" class="com.sdyu.ba04.PrimarySchool" >
<property name="name" value="北京小学"/>
<property name="address" value="北京大兴岭"/>
</bean>
1.多个配置优势
1)每个文件的大小比一个文件要小很多,效率高
2)避免多人竞争带来的冲突。
如果你的项目有多个模块(相关的功能在一起),一个模块一个配日志文件。
学生考勤模块一个配置文件,张三
学生成绩一个配置文件, 李四
多文件的分配方式:
1.按功能模块,一个模块一个配置文件
2.按类的功能,数据库相关的配置文件一个文件配置文件,做事务的功能一个配置文件,做service功能的一个配置文件等。
<import resource="classpath:spring-school.xml"/>
<import resource="classpath:spring-student.xml"/>
<import resource="classpath:spring-*.xml"/>
基于注解的DI
通过注解完成java对象的创建,属性赋值
使用注解的步骤
1.加入maven的依赖,spring-context,在你加入spring-context的同时,间接加入spring-aop的依赖。
使用注解必须使用spring-aop依赖
2.在类中加入spring的注解(多个不同功能的注解)
3.在spring的配置文件中,加入一个组件扫描器的标签,说明在你项目中的位置
定义bean的注解@Component
1.@Component
/**
-
@author @Component 创建对象 等同于的功能 -
属性 value 就是对象的名称,也就是bean的id值, -
value的值是唯一的,创建的对象在整个spring容器中就一个 -
位置:在类的上面 *
* @Component(value="myStudent")等同于
* <bean id="myStudent" class="com.sdyu.ba01.Student">
*
*/
声明组件扫描器
<context:component-scan base-package="com.sdyu.ba01"></context:component-scan>
指定多个包的方式 :三种方式
<context:component-scan base-package="com.sdyu.ba01"/>
<context:component-scan base-package="com.sdyu.ba02"/>
<context:component-scan base-package="com.sdyu.ba01;com.sdyu.ba02"/>
<context:component-scan base-package="com.sdyu"/>
1)@Component(value="myStudent")
2)@Component("myStudent") 常用
3)//不指定对象名称,由spring提供默认名称:类名的首字母小写
@Component
面试题 spring和@Component 功能一致,创建对象的注解还有:
- 1.@Repository(用在持久层类的上面):放在dao的实现类上面,
- 表示创建dao层对象,dao对象是能访问数据库的。
- 2.@Service(用在业务层类的上面):放在service的实现类上面,创建service,
- service对象是做业务处理,可以有事务等功能的。
- 3.@Controller(用在控制器的上面):放在控制器(处理器)类的上面,创建控制器对象的
- 以上三个注解的使用语法和Component一样的,都能创建对象,但是这 三个注解还有额外的功能。
- @Repository和@Service和@Controller是给项目分层的。
简单类型属性注入@Value
@Value:简单类型的属性赋值
@Value(value="张飞")
private String name;
@Value(value="29")
private Integer age;
@Value("张飞")
private String name;
@Value("29")
private Integer age;
放在set方法上面(少用)
byType自动注入@Autowired
引用类型的赋值
属性:requied,是一个boolean类型的,默认为true
- required-true:表示引用类型赋值失败,程序报错,并终止执行
- required-false:引用类型如果赋值失败,程序正常执行,引用类型是null
- 推荐使用(true)
引用类型
* @Autowired:spring框架提供的注解,实现引用类型的赋值
* spring中通过注解给引用类型赋值,使用的是自动注入原理,支持byName,byType
*
* @Autowired:默认使用 的是byType自动注入
*
* 位置:
* 1)在属性定义的上面,无需set方法,推荐使用
* 2)在set方法上面
byName自动注入@Autowired与@Qualifier
- 如果要使用byName方式,需要做的是:
- 1.在属性上面加入@Autowired
- 2.在属性上面加入@Qualifier(value=“bean的id”) :表示使用指定的bean完成赋值
*/ @Autowired @Qualifier(“mySchool”) private School school;
JDK注解@Resource自动注入
@Resource //默认byName自动注入,如果byName赋值失败,在使用ByType
注解与XML的对比
ml配置文件值与源代码分离 用起来费事费力。
注解方便 要学好 但代码很乱 对代码有侵入性
<context:property-placeholder location="classpath:test.properties"/>
myname=“zhangsna” myage=23
注解为主,配置文件为辅
junit测试使用
单元测试,一个工具类,做测试方法使用的。
单元:指定的是方法,一个类中有很多方法,一个方法称为单元
使用单元测试:
加入依赖:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
2.创建测试作用的类:叫做测试类
? src/test/java目录中创建类
3.创建测试方法
? 1)public方法
? 2)没有返回值void
? 3)方法名称自定义,建议名称是test,你要测试方法名称
? 4)方法没有参数
? 5)方法的上面加入@Test,这样的方法是可以单独执行的,不用使用main方法
AOP面向切面编程
动态代理
动态代理是指,程序在整个运行过程中根本不存在目标类的代理类,目标对象的代理对象只是有代理生成工具(不是真实定义的类)在程序运行时由JVM根据反射等机制动态生成的。代理对象与目标对象的代理关系在程序运行时才确立。
JDK动态代理
? 动态代理的实现方式常用的有两只:使用JDK的Proxy,与通过CGLIB生成代理。
jdk的动态要求目标对象必须实现接口,这是java设计上的要求。
从jdk1.3以来,java语言通过java.lang.reflect包提供三个类支持代理模式Proxy,Method和inovcationHandler.
CGLIB(了解)
? CGLIB(Code Generation Library)是一个开源项目。是一个强大的,高性能,高质量的Code生成类库,它可以运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如SpringAOP
? 使用JDK的Proxy实现代理,要求目标与代理类实现相同的接口上。若目标类不存在接口,则无法使用该方式实现。但对于无接口的类,要为其创建动态代理,就要使用CGLIB来实现。
? GCLIB代理的生成原理是生成目标类子类,而子类是增强过的,这个子类对象就是代理对象。所以,使用CGLIB生成动态代理,要求目标类必须能够继承,即不能是final的类。
? GCLIB经常被应用在框架中,例如Spring,Hibernate 等。cglib的代理效率高于jdk。项目中直接使用动态代理的地方不多。一般都使用框架提供的功能。
|