学习内容是跟着b站大佬遇见狂神说学习的,大家有兴趣建议去关注学习。
文章目录
- 1.Spring
- 1.1 简介Spring
- 1.2 优点
- 1.3 组成
- 1.4 拓展
- 2.IOC理论推导
- 3.HelloSpring
- 4.IOC创建对象的方式
- 5.Spring配置
- 5.1 别名
- 5.2 Bean的配置
- 5.2 import
- 6.依赖注入
- 6.1 构造器注入
- 6.2 Set注入(重点)
- 6.3 拓展方式注入
- 6.4 bean的作用域
- 7.Bean的自动装配
- 7.1 测试
- 7.2 ByName自动装配
- 7.3 ByType自动装配
- 7.4 使用注解实现自动装配
- 8.使用注解开发
- 9.使用Java的方式配置Spring
- 10.代理模式
- 10.1静态代理
- 10.2 加深理解
- 10.3 动态代理
- 11.AOP
- 11.1 什么是AOP
- 11.2 AOP在Spring中的作用
- 11.3 使用Spring实现AOP
- 12.整合Mybatis
- 12.1 mybatis
- 12.2 Mybatis-spring
- 13.声明式事务
- 13.1 回顾事务
- 13.2 spring中的事务管理
Spring: 简化企业开发的复杂性,使现有技术更加容易使用,比如Servlet
官网:https://spring.io/projects/spring-framework#overview
官网下载地址:https://repo.spring.io/release/org/springframework/spring/
GitHub:https://github.com/spring-projects/spring-framework
org.springframework spring-webmvc 6.0.9 org.springframework spring-jdbc 6.0.9
Spring是一个开源的免费的框架(容器)
Spring使一个轻量级的、非入侵的框架
控制反转(IOC)、面向切面编程(AOP)
支持事务的处理,对框架整合的支持
总结:Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架
现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提需要掌握Spring和SpringMVC。
弊端:发展太久之后,违背原有的理念,配置十分繁琐。
1.UserDao接口
2.UserDaoImpl实现类
3.UserService业务接口
4.UserServiceImpl业务实现类
在之前的业务中,用户的需求可能会影响我们原来的代码,需要根据用户的需求去修改源代码,如果程序代码量十分大,修改一次成本会很贵!
我们使用一个Set接口实现类
private UserDao userdao;
//利用set实现动态值的注入
public void setUserdao(UserDao userdao) {
this.userdao = userdao;
}
public void getUser(){
userdao.getUser();
}
这种思想从本质上解决了问题,程序员buoy那个再去管理对象的创建了,系统的耦合性大大降低,可以更加关注在业务的实现上。
Hello对象是谁创建的
hello对象是由Spring创建的
Hello对象的属性是怎么设置的
由Spring容器设置
这个过程就是控制反转
控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的。
反转:程序本身不创建对象,而是变成被动的接受对象。
依赖注入:就是利用set方法注入的
IOC是一种编程思想,由主动的编程变成被动的接受。
可以通过newClassPathXmlApplicationContext去浏览一下底层源码。
目前不需要在程序中去改动了,要实现不同的操作吗,只需要在xml配置文件中进行修改,所谓的IOC,就是用Spring来创建、管理和装配。
<bean id="user" class="com.baidu.pojo.User">
<constructor-arg index="0" value="狂神说Java"/>
</bean>
<bean id="user" class="com.baidu.pojo.User">
<constructor-arg type="java.lang.String" value="lihan"/>
</bean>
<bean id="user" class="com.baidu.pojo.User">
<constructor-arg name="name" value="lihan"/>
</bean>
在配置文件加载的时候,容器中管理的对象就已经初始化了
<!-- 别名,如果添加了别名,就可以使用别名来获取这个对象-->
<alias name="user" alias="userNew"/>
<!-- -->
<!-- id:bean的唯一标识符,也就是相当于对象名
class:bean对象所对应的全限定名:包名+类型
name:也是别名,而且name也可以取多个别名
-->
<bean id="userT" class="com.baidu.pojo.UserT" name="user2 u2,u3,u4">
<property name="name" value="baidu"/>
</bean>
一般适用于团队开发,可以将多个配置文件导入合并为一个
假设,现有项目中有多个人开发,这三个人负责不同的类开发,不同的类需要注册在不同的bean中,可以利用import将所有人的beans.xml合并为一个总的。
<import resource="beans.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml">
使用的时候直接用总的配置就可以了
看前
环境搭建:
1.复杂类型
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
2.真实测试对象
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbies;
private Map<String,String> card;
private Set<String> games;
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--第一种,普通值注入,value-->
<bean id="student" class="com.baidu.pojo.Student">
<property name="name" value="lihan"/>
</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.getName());
}
}
5.完善注册信息
<?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">
<bean id="address" class="com.baidu.pojo.Address">
<property name="address" value="吉林"/>
</bean>
<bean id="student" class="com.baidu.pojo.Student">
<!--第一种,普通值注入,value-->
<property name="name" value="lihan"/>
<!--第二种,Bean注入,ref-->
<property name="address" ref="address"/>
<!--数组-->
<property name="books">
<array>
<value>红楼梦</value>
<value>西游记</value>
<value>三国演义</value>
<value>水浒传</value>
</array>
</property>
<!--List-->
<property name="hobbies">
<list>
<value>抽烟</value>
<value>喝酒</value>
<value>烫头</value>
</list>
</property>
<!--Map-->
<property name="card">
<map>
<entry key="身份证" value="412721199805161434"/>
<entry key="银行卡" value="6217002430044188986"/>
</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="学号">202108034</prop>
<prop key="姓名">李涵</prop>
</props>
</property>
</bean>
</beans>
我们可以使用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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--p命名空间,可以直接注入属性的值:property-->
<bean id="user" class="com.baidu.pojo.User" p:name="李涵" p:age="25"/>
<!--c命名空间,通过构造器注入:construct-args-->
<bean id="user2" class="com.baidu.pojo.User" c:age="25" c:name="李涵"/>
</beans>
测试:
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
User user = context.getBean("user2", User.class);
System.out.println(user);
}
注意点:p和c不能直接使用,需要导入xml约束
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
<bean id="user2" class="com.baidu.pojo.User" c:age="25" c:name="李涵" scope="singleton"/>
<bean id="user2" class="com.baidu.pojo.User" c:age="25" c:name="李涵" scope="prototype"/>
在Spring中有三种装配的方式
环境搭建
<!--byName:会自动在容器上下文中查找,和自己对象set方法对应的值的bean id-->
<bean id="people" class="com.baidu.pojo.People" autowire="byName">
<!--byType:会自动在容器上下文中查找,和自己对象属性相同的bean -->
<bean id="people" class="com.baidu.pojo.People" autowire="byType">
小结
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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
@Autowired
直接在属性上使用即可,也可以在set方法使用。
使用Autowired就可以不用编写Set方法,前提是自动装配的属性在IOC(Spring)容器中存在,且符合ByType。
@Resource注解
小结:@Resource和@Autowired的区别:
在Spring4之后,要使用注解开发,必须保证aop包的导入。
使用注解需要导入context约束,增加注解的支持。
2.属性注入
@Component
public class User {
@Value("李涵")
public String name;
// 等价于
public void setName(String name){
this.name = name;
}
}
@Autowired:自动装配通过类型、名字,如果Autowired不能唯一自动装配属性,则需要通过@Qualifier(value="xxx")
@Nullable: 字段标记了这个注解,说明这个字段可以未null
@Resource:自动装配通过名字、类型
@Component
@Scope("prototype")
public class User {
@Value("李涵")
public String name;
// 等价于
public void setName(String name){
this.name = name;
}
}
小结
xml和注解:
xml与注解最佳实践:
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.baidu.pojo"/>
<context:annotation-config/>
角色分析:
代理步骤:
1.接口
//租房
public interface Rent {
public void rent();
}
2.真实角色
//房东
public class Host implements Rent{
public void rent(){
System.out.println("房东要出租房子");
}
}
3.代理角色
public class Porxy implements Rent{
private Host host;
public Porxy() {
}
public Porxy(Host host) {
this.host = host;
}
public void rent(){
seehouse();
fare();
host.rent();
}
//看房
public void seehouse(){
System.out.println("中介带你看房");
}
//收中介费
public void fare(){
System.out.println("收中介费");
}
}
4.客户端访问代理角色
public class Client {
public static void main(String[] args) {
//房东要出租房子
Host host = new Host();
//代理
Porxy proxy = new Porxy(host);
proxy.rent();
}
}
代理模式的好处:
缺点:一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率会变低
需要了解两个类:Proxy:代理,InvocationHandler:调用处理程序
AOP使是面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP
的延续,是软件开发的一个热点,也是Spring框架的一个重要内容,是函数式编程的一种衍生泛型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
提供声明式事务,允许用户自定义切面
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:
AOP在不改变原有代码的情况下,去增加新的功能
使用AOP需要导入一个依赖包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
方式一:使用Spring的API接口【抓哟SpringAPI接口实现】
方式二:自定义来实现AOP【主要是切面定义】
方式三:使用注解实现
步骤:
1.导入相关jar包
2.编写配置文件
3.测试