一,spring是什么
Spring是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的容器框架
理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架
优点:
弊端:违背了原有的技术理念:配置太过繁琐,被称为“配置地狱”
官方文档:core technologies
二,Spring框架由七个定义明确的模块组成
- Spring Context:提供框架式的Bean访问方式,以及企业级功能(JNDI、定时任务等);
-
Spring Core:核心类库,所有功能都依赖于该类库,提供IOC和DI服务;
-
Spring AOP:AOP服务;
-
Spring Web:提供了基本的面向Web的综合特性,提供对常见框架如Struts2的支持,Spring能够管理这些框架,将Spring的资源注入给框架,也能在这些框架的前后插入拦截器;
-
Spring MVC:提供面向Web应用的Model-View-Controller,即MVC实现。
-
Spring DAO:对JDBC的抽象封装,简化了数据访问异常的处理,并能统一管理JDBC事务;
-
Spring ORM:对现有的ORM框架的支持;
三,现代化的开发就是基于spring容器的开发,
1.springboot :一个快速开发的脚手架
约定大于配置
2.springcloud:
springCloud是基于SpringBoot实现的
四,控制反转和面向切面
IOC:(获得依赖对象的方式反转了,对象由spring来创建,管理和装配)
1.控制反转:从本质上解决了问题,使我们程序员不用再去管理对象的创建了
系统的耦合性大大降低,可以更专注于业务的实现(IOC的原型)
1)以前:程序是需要程序员主动创建对象,控制权在开发人员手上
2)使用了set方法,程序不再具有主动性,而是变成了被动的接受对象,主动权在用户手上
3)配置:
<?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">
</beans>
ref: 引用Spring容器中创建好的对象
value:具体的值,基本数据类型
4)IOC创建对象的方法:
1.默认使用无参构造创建对象
2. 手动配置有参构造:constructor
1)下标赋值:index
2)通过类型创建(不建议)
3)通过参数名:name
5)在配置文件加载的时候,容器中管理的对象就已经初始化了,(容器类似于婚介所,只有对象注册到了婚介所,当容器applicationcontext被创建,被管理的对象也就存在,也就是被初始化了)
五,spring的配置
1.别名:
alias:—–>如果添加了别名,我们也可以通过别名获取对象
2.Bean的配置:
id:bean的唯一标识符,也就是相当于我们的对象名
class:bean的全限定名“包名+类名”(bean对象所对应的全限定名)
name: 也是别名:而且name比alias更高级,可以同时取多个别名(逗号或空格或分号分割)
ref:引用Spring容器中创建好的对象
value:具体的值,基本数据类型
3.import:
1)这个import,一般用于团队开发,可以将多个配置文件,导入合并为一个
2)假设项目中有多个人开发,这三个人负责不同类的开发,不同类需要注册到不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的
张三:beans
李四:beans2
王五:beans3
applicationContext.xml:
<import resource=”beans.xml”/>
<import resource=”beans2.xml”/>
<import resource=”beans3.xml”/>
使用的时候,直接使用总的配置就好了
六,DI依赖注入
1.构造器注入:
2.通过set方式注入
依赖注入:set注入
依赖:bean对象的创建依赖于容器
注入:bean对象中的所有属性,由容器来注入
环境搭建:
1.复杂类型
2.真实测试对象
<bean id="student" class="com.kuang.pojo.Student">
<!--第一种,普通注入-->
<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="1234543234543234"/>
<entry key="银行卡" value="3ueqrqyrqoyrqywqo"/>
</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="学号">190970070</prop>
<prop key="性别">男</prop>
<prop key="姓名">小俊</prop>
</props>
</property>
</bean>
3.其他方式注入
注意:这两种不能直接使用,需要去导入约束,从官方文档去拿
1)p命名注入 xmlns:p=”http://www.springframework.org/schema/p”
2)c命名注入 xmlns:c=”http://www.springframework.org/schema/c”
<!–p命名空间,可以直接注入属性的值–>
<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=”小俊俊”/>
4.bean的作用域:
1)单例模式:singleton:
spring 默认机制
<bean id=”user2″ class=”com.kuang.pojo.User” c:age=”18″ c:name=” 小俊俊” scope=”singleton”/>
2)原型模式:prototype:
每次从容器中get的时候,都会产生一个新对象
3)其他的在web中才用到
七.Bean的自动装配
自动装配是spring满足bean依赖的一种方式
spring会在上下文中自动寻找,并自动给bean装配属性
三种装配在方式:
1)在xml中显示的配置
2)在java中显示的配置
3)隐式的自动装配bean(重要)
1.byName自动装配
byName会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanID
<bean id="people" class="com.kuang.pojo.People" autowire="byName">
<property name="name" value="小俊俊呀!"/>
</bean>
2.byType自动装配
byName会自动在容器上下文中查找,和自己对象属性类型相同的beanID
<bean id="people" class="com.kuang.pojo.People" autowire="byType">
<property name="name" value="小俊俊呀!"/>
</bean>
3.小结:
-
byname的时候:需要保证所有bean的
id唯一
,并且这个bean需要和自动注入的
属性的set方法值一致
-
byname的时候:需要保证所有bean的
class唯一
,并且这个bean需要和自动注入的
属性的类型值一致
4) 使用注解实现自动配置:
The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML.
要使用注解须知:
1.导入上下文约束
2.导入约束(context约束):<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>
3.@Autowired:
1)直接在属性上使用即可,也可以在set方式上使用
使用autowired,我们可以不用编写set方法了,前提是你这个自动装配的实行在IOC容器中 已 经存在了,并且名字符合byName!
2)科普:
1,
@Nullable
:字段如果标记了这个注解,那说明这个字段可以为空
2,@Qualifier:如果自动装配环境比较复杂,自动装配无法通过一个注解完成的时候,我们可以使用@Qualifier(value=”xxx”)去配合@Autowired使用,指定一个唯一的bean对象注入
4,@Resource:
@Resource:(name=”cat”)
5,@Resource和@Autowired区别:
1).都是用来自动装配的,都可以放到属性字段上
2)@Autowired通过byname的方式实现,而且必须要求这个对象存在
3)@Resource默认通过byname方式实现没如果找不到名字,则通过byType,,如果两个都找不到,就会报错(也可以通过name去指定)
八.使用注解开发
-
在spring4之后,如果要使用注解开发,必须要保证aop的包已经导入了
-
使用注解需要导入context约束,增加注解支持
1.bean注入:@Component
2.属性注入:@Value
3.衍生的注解:
- Component有几个衍生的注解,在web开发中,会按照MVC三层架构分层
- dao:【@Repository】
- service:【@Service】
- controller:【@Controller】
- 这四个注解的功能都是一样的,都是代表将某个类注册到spring容器中,装配
4.自动装配
- @Autowired:
- @Nullable:
- @Resource:
5.作用域:
@Scope:指定模式:单例(singleton),原型(prototype)
6.小结
-
xml与注解:
- xml更加万能,适用于任何场合,维护更加简单
- 注解不是自己的类使用不了,维护相对复杂
-
xml与注解最佳实践
- xml用来管理bean:
- 注解只负责完成属性的注入
-
我们在使用的过程中,只需要注意一个问题:
必须让注解生效,就必须要开启注解支持
九,完全使用java的方式配置spring(新特性)
我们现在要完全不使用spring的xml配置了,全权交给java来做
javaConfig是spring的一个子项目
这种纯java的配置方式,在springboot中随处可见
-
实体类:
-
package com.kuang.pojo; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; @Component//这个注解表示这个对象呗spring接管了 public class User { private String name; public String getName() { return name; } @Value("小俊")//属性注入值 public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } }
-
-
配置类:
-
package com.kuang.config; import com.kuang.pojo.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration//这个也会被spring容器托管,因为他本身就是一个组件,这个注解代表是一个配置类,就和我们之前看到的beans.xml是一样的 public class KuangConfig { //注册一个bean,就相当于我们写的一个bean标签 //这个方法的名字,就相当于bean标签中的id属性 //这个方法的返回值,就相当于bean标签中的class属性 @Bean public User getUser() { return new User();//就是返回要注入到bean的对象 } }
-
-
测试类:
-
import com.kuang.config.KuangConfig; import com.kuang.pojo.User; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MyTest { public static void main(String[] args) { //如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象来加载 ApplicationContext context = new AnnotationConfigApplicationContext(KuangConfig.class); User getUser = (User) context.getBean("getUser"); System.out.println(getUser.getName()); } }
-
十,代理模式:
为什么要学代理模式?因为这就是SpringAOP的底层!(SpringAOP和SpringMVC)
代理模式分类:
1)静态代理
:
-
角色分析:
- 抽象角色:一般会用接口或者抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
- 客户:访问代理对象的人
-
代码步骤:
- 接口:
-
//租房 public interface Rent { public void rent(); }
- 真实角色:
-
//房东 public class RentHostImpl implements Rent { @Override public void rent() { System.out.println("房东要出租房子!"); } }
- 代理角色:
-
//中介 public class RentProxyImpl implements Rent { private RentHostImpl rentHost; public RentProxyImpl() { } public RentProxyImpl(RentHostImpl rentHost) { this.rentHost = rentHost; } @Override public void rent() { rentHost.rent(); seeHouse(); heTong(); fare(); } //看房 public void seeHouse() { System.out.println("中介带你看房"); } //签合同 public void heTong() { System.out.println("签租赁合同"); } //收中介费 public void fare() { System.out.println("收中介费"); } }
- 客户端访问代理角色:
-
//客户 public class Client { public static void main(String[] args) { RentHostImpl rentHost = new RentHostImpl(); rentHost.rent(); //代理 RentProxyImpl rentProxy = new RentProxyImpl(rentHost); rentProxy.rent(); } }
-
代理模式的好处:
- 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
- 公共也就是交给代理角色,实现了业务的分工
- 公共业务发生扩展的时候,方便集中管理
-
缺点:
- 一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率会变低
2)动态代理(为了改变静态代理的缺点)
- 动态代理和静态代理角色一样
- 动态代理是动态生成的,不是我们直接写好的
-
动态代理分为两大类:基于接口的动态代理,基于类的动态代理
-
基于接口:jdk动态代理
-
基于类:cglib
-
java字节码实现:javasist
-
-
需要了解两个类::Proxy代理, InvocationHandler调用处理程序
-
动态代理的好处:
- 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
- 公共也就是交给代理角色,实现了业务的分工
- 公共业务发生扩展的时候,方便集中管理
-
一个动态代理类代理的是一个接口,一般就是对应一类业务
-
一个动态代理类可以代理多个类,只要是实现了同一个接口即可(rent接口,rent接口的两个实现类,只需要写一个动态代理类)
十一,什么是AOP
1)
2)
3)使用spring实现AOP
-
【重点】:使用aop织入,需要导入一个依赖包
-
<dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.6</version> </dependency> </dependencies>
- 方式一:使用spring的api接口
- 的
- 方式二:使用自定义类来实现AOP