1.1简介:
spring:使现有的技术更加容易使用,整合现有技术框架
-
SSH:Struct+Spring+Hibernate
-
SSM:SpringMVC+Spring+Mybatis
1.2优点:
-
Spring是一个开源的免费的框架(容器)
-
Spring是一个轻量级的,非侵入式的框架
-
控制反转(IOC),面向切面编程(AOP)
-
支持事务的处理,对框架整合的支持
Spring就是一个轻量级的控制反转(IOC)和面向编程(AOP)的框架
1.3组成
-
Spring Boot:
是一个快速开发的脚手架,基于SpringBoot可以快速的开发单个微服务。约定大于配置!!
-
Spring Cloud
是基于SpringBoot实现 的。
2.IOC理论指导
1、UserDao接口
2、UserDaoImpl实现类
3、UserService业务接口
4、UserServiceImpl业务实现类
用set接口实现:
private userDao userDao;
//利用set进行动态实现值的注入
public void setUserDao(UserDao userDao){
this.userDao=userDao;
}
系统的耦合性降低,注重在业务的实现上,这是IOC的原型。
IOC本质:
控制反转IOC,是一种设计思想,DI(依赖注入)是实现IOC的一种方法。没有loC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XMl或注解)并通过第三方去生产或获取特定对象的费那事,在Spring中实现控制反转的是IOC容器,其方法是依赖注入(DI)。
3.HelloSpring
<!--使用spring来创建对象,在spring这些都称为Bean
类型 变量名=new 类型();
Hello hello=new Hello();
id =变量名
class=new 的对象
property相当于给对象中的属性设置一个值
-->
控制:传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的
反转:程序本身不创建对象,而变成被动的接收对象。
依赖注入:利用set的方法来进行注入
IOC是一种编程思想,由主动的编程变成被动的接收
我们可以通过newClassPathXmlApplicationContext去浏览一下底层源码
4.IOC创建对象
1.使用无参构造创建对象,默认!
2.有参创建对象:
1.下标赋值:
<&ndash – >
<bean id="user" class="com.kuang.pojo.user">
<constructor-arg index="0" value="java"/>
<bean>
2.类型
<bean id="user" class="com.kuang.user">
<consturctor-arg type="java.lang.string" value="qinjiang"/>
<bean>
3.参数:通过参数名来设置
<bean id="user" class="com.kuang.pojo.User">
<constructor-arg name="name" value="qinjian"/>
</beans>
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了!
5.Spring配置
5.1 别名
如果添加了别名,我们也可以通过别名来获取这个对象!
<alias name="user" alias="userNew"/>
5.2 bean配置
id: bean的唯一标识符,就相当于我们的对对象名。
class: bean 对象所对应的全限定名:包名+类型。
name:也是别名。
<bean id="userT" class="com.kuang.pojo.UserT" name="user2 u2,u3,u4">
<property name="name" value="老胡"/>
</bean>
5.3 improt
一般用于团队开发,可以将多个配置文件导入合并为一个。
假设;现在项目中由多个人开发,这三个人负责不同的类开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的!
-
张三
-
李四
-
王五
-
applicationContext.xml
<imprit resource="beans.xml"/>
<imprit resource="beans2.xml"/>
<imprit resource="beans3.xml"/>
使用的时候,直接使用总的配置就可以!!!
6.依赖注入
6.1构造器注入:
简单提一下:
这里有详解:[深度分析Spring中的构造器注入|-| [- | |_ ()-CSDN博客_构造器注入](深度分析Spring中的构造器注入_|-| [- |_ |_ ()-CSDN博客_构造器注入)
6.2set方式注入【重点】:
-
依赖注入:Set注入
1.依赖:bean对象的创建依赖于容器!
2.注入:bean对象中的所有属性,由容器注入!
【环境搭建】
1.复杂类型
public class Address{ private String address; public String getAddress(){ return address; } public void class setAddress(String address){ this.address=address; } }
2.真实测试对象
public class student{ private String name; private Address address; private String[] books; private List<String> hobbys; privae Map<String,String> card; private Set<String> game; private String wife; private Properties info; }
3.bean.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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <bean id="student" class="com.kuang.pojo.student"> <property name="name" vlaue="胡"> </bean> </beans>
4.测试类
public class MyTest{ public static void main(String[] args){ ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml"); Student student=(student) context.getBean("student"); System.out.println(student.getAddress()); } }
<bean id="address" class="comkuang.pojo.Address"/>
<bean id="student" class="com.kuang.pojo.Student">
<!--第一种:普通值注入,value-->
<property name="name" value="胡"/>
<!--第二种:Bean注入 ref-->
<property name="address" ref="address"/>
<!--数组-->
<property name="books">
<array>
<value>红楼梦</value>
<value>西游记</value>
<value>水浒传</value>
<value>三国演义</value>
</array>
</property>
<!--list-->
<property name="hobbys">
<list>
<value>听歌</value>
<value>改代码</value>
<value>看电影</value>
</list>
</property>
<!--Map-->
<property name="card">
<map>
<entry key="身份证" value="111111222222333333"></entry>
<entry key="银行卡" value="123321321313132211"></entry>
</map>
</property>
<!--Set-->
<property name="games">
<set>
<value>LOL</value>
<value>COC</value>
<value>BOB</value>
</set>
</property>
<!--null-->
<property name="wife">
<null/>
</property>
<!--Properties-->
<property name="info">
<props>
<prop key="driver">201901</prop>
<prop key="url">男</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
6.3扩展方式注入:
我们可以使用p命令空间和c命令空间进行注入。
使用!
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!--p命名空间注入,可以直接注入属性的值:property-->
<bean id="user" class="com.kuang.pojo.user" p:name="胡" p:age="18"/>
<!--c命名空间注入,通过构造器注入:construct-args-->
<bean id="user2" class="com.kuang.pojo.User" c:age="18" c:name="胡"/>
</beans>
测试:
@Test
public void test2(){
ApplicaionContext context=new classPathxmlApplicationContext("userbean.xml");
User user=context.getBean("user2",User.class);
}
注:p命名和c命名空间不能直接使用,需要导入xml的约束!
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springfamework.org/schema/p"
6.4 bean的作用域
创建的所有实例都只有一个
1.单例模式:(spring默认机制:singleton)
<bean id="user2" class="com.kuang.pojo.User" c:age="18" c:name="胡" scope="singleton"/>
2.原型模式:每次从容器中get的时候,都会产生一个新的对象!
<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
3.其余的 request、session、application、这些只能在web开发中使用到!
7、Bean的自动装配
-
自动装配是Spring满足bean依赖的一种方式
-
Spring会在稳重上下文中自动寻找,并自动给bean装配属性
在Spring中有三种装配的方式:
1.在xml中显示的配置
2.在java中显示配置
3.隐式的自动装配bean【重要】
7.1测试
1.环境搭建
7.2 ByName自动装配
<!--
byName 会自动在容器上下文中查找,和自己对选哪个set方法后面的值对应的beanid
-->
<bean id="people" class="com.kuang.pojo.People" autowire="byName">
</bean>
7.3 ByType自动装配
<bean class="com.kuang.pojo.Cat"/>
<bean class="com.kuang.pojo.Dog"/>
<!--
byName:会自动在容器上下文中查找,和自己对象set方法后面的值对对应的beanid!
byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean!
-->
<bean id="people" class="com.kuang.pojo.People" autowire="byType">
<property name="name" value="胡"/>
</bean>
小结:
-
byname的时候,需要保证所有的bean的id位移,并且这个bean需要和自动注入的属性的set方法的值一致
-
bytype的时候,需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性的类型一致!
7.4使用注解实现自动装配
jdk1.5支持的注解,spring2.5就支持注解l!
The introduction of annotation-based configruation raised the question of whether this approach is"better" than XML.
要使用注解须知:
1.导入约束,context约束
2.配置注解的支持: context:annotation-config/
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
@Autowired
直接在属性上使用即可,也可以在set方式上使用!
使用Autowired我们可以不用编写Set方法,前提是你这个自动装配的属性在IOC(Spring)容器中存在,且符合名字byname!
@Nullable 字段标记了这个注解,说明这个字段可以为null
public @interface Autowired{
boolean required() default true;
}
ppublic class People{
//如果显示定义了Autowired的requird属性为false,说明这个对象可以为null,=否则不允许为空
@Autowired(required=flase)
private Cat cat;
@Autowired;
private Dog dog;
private String name;
}
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解[@Autowired]完成的时候,我们可以使用@Qualifier(value="xxx")去配置@Autowired的使用,指定一个唯一的bean对象注入!
public class People{
@Autowired
@Qualifier(value="catll")
private cat cat;
@Autowired
@Qualifier(value="dog222")
private Dog dog;
private String name;
}
@Resource注解
public class People{
@Resource(name ="cat2")
private Cat cat;
@Resource
private Dog dog;
}
小结:
@Resource和@Autowired的区别:
-
都是用来自动装配的,都可以放在属性字段上
-
@Autowired通过byType的方式实现,而且必须要求这个对象存在!【常用】
-
@Resource默认通过byname的方式去实现,如果找不到名字,则通过byType来实现,如果两个都找不到的情况下,就报错!【常用】
-
执行顺序不同:
@Autowired通过byType方式实现。@Resource默认通过byname的方式实现。
8、使用注解开发
在spring4之后要使用注解开发,必须保证aop包导入
使用注解开发需要导入context的约束,增加注解的支持!
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
</beans>
1、bean
2、属性如何注入
@Component
public class User{
public String name;
//相当于<property name="name" vlaue="kuang"/>
@value("kuang")
public void setNmae(Stirng name){
this.name=name;
}
}
3、衍生的注解
@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层:
-
dao 【@Repository】
-
service 【@service】
-
controller 【@Controller】
-
这四个功能注解都是一样的,都是代表将某个类注册到Spring中,装配Bean。
4、自动装配置
-@Autowird:自动装配通过类型,名字
如果是Autowired不能唯一装配上属性,则需要通过@Qualifier(value="xxx")
-@Nullable:字段标记了这个注解,说明这个字段可以为null
-@Resource:自动装配通过名字,类型
5、作用域
@Component
@Scope("prototype")
public class User{
public String name;
//相当于<property name="name" value="hu"/>
@value("hu")
public void setName(String name){
this.name=name;
}
}
6、小结
xml与注解:
-
xml更加万能,适用于任何场合!维护简单方便
-
注解 不是自己实用不了,维护相对复杂
xml注解最佳实践:
-
xml用来管理bena
-
注解只负责完成属性的注入
-
我们在使用的过程中,,只需要注意一个问题:必须让注解生效,就需要开启注解的支持!!
<!-- 指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.kuang"/>
<context:annotation-config/>
9、使用java的方式配置Spring
我们现在要完全不使用Spring的xml配置,全权交给java来做!
JavaConfig是Spring的一个子项目在Spring4之后,
实体类:
//这里这个注解的意思是,说明这个类被Spring接管了,注册到了容器中
@Component
public class User{
private String name;
public String getName(){
return name;
}
@Value("QINJIANG")//属性注入值
public void setName(String name){
this.name=name;
}
@Override
public String toString(){
return "User"{"+
"name='"+name+"\''+
'}';
}
}
配置文件;
//上面部分包未写出,自行补全
//这个也会Spring容器托管,注册到容器中,因为它本身就是一个@Component
//@Configuration代表这是一个配置类,就和我们之前看的beans。mxl
@Configuration
@ComponentScan("com.kuang.pojo")
@Import(KuangConfig2.class)
public class kuangConfig{
//注册一个bean,就相当于我们之前写的一个bean标签
//这个方法的名字,就相当于bean标签中的id属性
//这个方法的返回值,就相当于bean标签中的class属性
@Bean
public User user(){
return new User();//就是返回要注入到bean的对象;
}
}
测试类:
public class MyTest{
public sttic void main(String[] args){
//如果完全使用了配置类的方式去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载!
ApplicationContext context=new AnnotationConfigApplicationContext(kuangCOnfig.class);
User getUser=(User) context.getBean("user");
System.out.println(getUser.getName());
}
}
这种纯java的配置方式,在SpringBoot中随处可见!!
10、代理模式
这就是SpringAOP的底层!【SpringAOP和SpringMVC】
代理模式的分类:
-
静态代理
-
动态代理
10、1 静态代理
角色分析:
-
一般使用接口或者抽象类来解决
-
真实代理:被代理的角色
-
代理角色:代理真实角色,代理真实角色后,我们一般会做一下附属操作!
-
客户:访问代理对象的人
代码步骤:
1、接口
//租房
public interface Rent{
public void rent();
}
2、真实角色
//房东
public class Host implements Rent{
public void rent(){
System.out.println("房东要出租房子!!");
}
}
3、代理角色
public class Proxy implements Rent{
private Host host;
public Proxy(){
}
public Proxy(Host host){
this.host=host;
}
public void rent(){
seehouse();
host.rent();
hetong();
fare();
}
//看房
public void seeHouse(){
System.out.println("中介带你看");
}
//看房
public void hentong(){
System.out.println("签租赁合同");
}
//收中介费
public void fare(){
System.out.println("收中介费");
}
}
4、客户端访问代理角色
public class Client{
public static void main(String[] args){
//房东要租房子
Host host=new Host();
//代理,中介要帮房东租房子,但是,代理角一般会有一些附属操作!
Proxy proxy=new Host();
//你不用面对房东,直接找中介租房即可!
proxy.rent();
}
}
代理模式的好处:
-
可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
-
公共的业务交给代理角色,实现业务的分工
-
公共业务发生扩展的时候,方便集中管理
缺点:
-
一个真实角色会产生一个代理角色,代码量会翻倍,开发效率比较低。
10、2 加深理解
代码:对应08-demo02;
10、3 动态代理
1.动态代理和静态代理角色一样
2.动态代理的的代理类事动态生成的,不是直接写好的!
3.动态代理分为两大类:基于接口的动态代理,基于类的动态代理
-
基于接口····JDK动态代理【这里使用的】
-
基于类:cglib
-
java字节码实现:javasist
需要了解两个类:proxy:代理、InvocationHander:调用处理程序。
动态代理的好处:
-
可以使真实角色的操作更加纯粹,不用去关注一些公共的业务!
-
公共的业务交给代理角色,实现业务的分工!
-
公共业务发生扩展的时候,方便集中管理!
-
一个动态代理类代理的是一个接口,一般就是对应的一类业务!
-
一个动态代理类可以代理多个类,只要是实现了同一个接口即可!
11、AOP
11.1 什么是AOP
AOP (Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
11.2 AOP在Spring中的作用
-
提供声明式事务;允许用户自定义切面
-
横切关注点;跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如口志,安全,缓存,事务等等....
-
·切面(ASPECT):横切关注点被模块化的特殊对象。即,它是一个类。
-
通知(Advice)︰切面必须要完成的工作。即,它是类中的一个方法。
-
目标(Target)︰被通知对象。
-
代理(Proxy):向目标对象应用通知之后创建的对象。
-
切入点(PointCut) :切面通知执行的“地点"的定义。
-
连接点JointPoint) :与切入点匹配的执行点。
在SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice。
即AOP在不改变原有代码的情况下,去增加新的功能
11.3 使用Spring实现AOP
【使用AOP织入,需要导入一个依赖包】
<!--https://mvnrepository.com.artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.sapectj</groupId>
<srtifcatId>sapectjweaver</srtifcatId>
</dependency>
方式一:使用Spring的AOP接口【主要是Spring和API接口实现】
方式二:使用自定义类来实现【主要是切面定义】
方式三:使用注解实现!
12、整合Mybatis
步骤:
1、导入相关jar包
-
junit
-
mybatis
-
mysql数据库
-
spring相关
-
aop织入
-
mybatis-spring【new】
2、编写配置文件
3、测试
12.1 回忆mybatis
1、编写实体类
2、编写核心配置文件
3、编写接口
4、编写Mapper.xml
5、测试
12.2 Mybatis-Spring
MyBatis-sping会帮助你将MyBatis代码无缝地整合到Spring中。它将允许MyBais参与到 Sping 的事务管理之中,创建映射器mapper和SqlSession并注入到bean 中,以及将 Mybatis的异常转换为spring的DataAcceseException。最终,可以做到应用代码不依赖于MyBatis,Spring 或 MyBatis-Spring.
1、编写数据源配置
2、sqlSessionFactory
3、sqlSessionTemplats
4、需要给接口加实现类
5、将自己写的实现类,注入到Spring中
6、测试使用
13、声明式事务
1、回顾事务
-
把一组业当成一个业务来做,要么都成功,要么都失败
-
事务在项目开发中,十分重要,涉及到数据的一致性问题
-
确保完整性和一致性
事务ACID原则:
-
原子性
-
一致性
-
隔离性:
多个业务可能操作同一个资源,防止数据损坏
-
持久性
事务一旦提交,无论发生什么问题,结果都不会再被影响,被持久化的写到存储器中。
2、spring中的事务管理
-
声明式事务:AOP
-
编程式事务:需要在代码中,进行事务的管理
配置声明式事务:
<bena id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bena>
结合AOP实现事务的织入:配置事务通知
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给方法配置事务-->
<!--配置事务的传播特性:propagation-->
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete"/>
<tx:method name="update"/>
<tx:method name="query"/>
</tx:attributes>
</tx:advice>
为什么需要事务?
-
如果不配置事务,可能存在数据提交不一致的情况;
-
如果不在Spring中配置声明式事务,我们就需要在代码中手动配置事务;
-
事务在项目开发中十分重要,涉及到数据的一致性和完整性问题。
文档已经上传,需要的自行下载,编写文档的软件是typora