Spring

使现有的技术更加容易使用,本身是一个大杂烩,整合现有的技术框架

1、优点

  • Spring是一个开源对的免费的框架
  • Spring是一个轻量级的、非入侵式的框架
  • 控制反转(IOC),面向切面编程(AOP)
  • 支持事务对的处理,对框架整合的支持

总结:Spring是一个轻量级的控制反转(IOC) 和面向切面编程(AOP)对的框架

2、扩展

1、Spring Boot

  • 一个快速开发的脚手架
  • 基于SpringBoot可以快速的开发单个微服务
  • 约定大于配置

2、Spring Cloud

Spring Cloud是基于SpringBoot实现的

因为现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握Spring及

SpringMVC承上启下对的作用

3、弊端

发展太久以后,违背了原来对的理念,配置十分繁琐,人称“配置地狱”

3、Spring配置

必须要导入

1
2
3
4
<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">

需要用到的架包

1
2
3
4
5
6
7
- spring-aop-4.2.5.RELEASE.jar
- spring-aspects-4.2.5.RELEASE.jar
- spring-beans-4.2.5.RELEASE.jar
- spring-context-4.2.5.RELEASE.jar
- spring-context-support-4.2.5.RELEASE.jar
- spring-core-4.2.5.RELEASE.jar
- spring-expression-4.2.5.RELEASE.jar

1、bean的配置

格式:

1
2
3
4
<bean id="" class="vo类地址" name=“别名”>
<property name="属性名" value="值" />
<property name="属性名" ref="别的beanid" />
</bean>

解析:

  • id = 变量名
  • class = new的对象
  • property 给对象的属性赋值
  • name = 属性名
  • value = 属性值
  • ref = 引用spring的对象

例:

1
2
3
4
5
<bean id="stu" class="vo.student" name="aa">
<property name="id" value="1" />
<property name="name" value="" />
<property name="age" value="18"/>
</bean>

注意:
vo.student这个属性类必须要有set方法,空构造,否则就会报错

2、import

一般用于团队开发,他可以将多个配置文件,导入合并为一个
语法:

1
<impost resource="Spring配置xml">

内容相同则会合并

3、代码实现

例:

1
2
3
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
student stu=context.getBean("aa",student.class);
System.out.println(stu);

4、依赖注入

  • 动态替换Bean依赖对象,程序更灵活
  • 更好实践面向接口编程,代码更清晰
  • 更好实践优先使用对象组合,而不是类继承
  • 增加Bean可复用性
  • 降低Bean之间耦合
  • 代码结构更清晰

1、构造器注入

介绍:根据属性类的构造方法一一对应注入,下标从0开始

例:

1
2
3
4
5
6

<bean id="stu" class="vo.stu">
<constructor-arg index="0" value="张三" />
<constructor-arg index="1" value="男" />
<constructor-arg index="2" value="18" />
</bean>

2、Set注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?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="user" class="vo.User" name="aa"> <!-- name中为vo -->
<property name="name" value="周志狗" /> <!--普通值注入-->
<property name="sex"><null/></property> <!-- 注入null -->
<property name="sex" value=""/> <!-- 注入空 -->
<property name="books"> <!--数组注入,跟list一样-->
<array>
<value>可以有多个</value>
</array>
</property>
<property name="map"> <!--map注入-->
<map>
<entry key="11" value="222" />
</map>
</property>

<property name="set"> <!-- set注入 -->
<set>
<ref bean="user"/> <!--当前页面name注入-->
<value>Pakistan</value> <!--普通注入-->
<value>USA</value>
<value>USA</value>
</set>
</property>
<property name="set">
<props>
<prop key="dirve">1111</prop>
</props>
</property>
</bean>
<beans>

注:必须要包含一个无参构造,否则将会报错

3、p注入

导包:

1
xmlns:p="http://www.springframework.org/schema/p

例:

1
<bean id="user" class="vo.User" p:name='姓名' p:age="11" />

4、c注入

必须导包:

1
xmlns:c="http://www.springframework.org/schema/c"

例:

1
<bean id="user" class="vo.User" c:name='姓名' c:age="11" />

注意:c注入是根据构造方法注入的

5、Bean的自动装配

介绍:

  • 自动装配是spring满足bean依赖的一种方式
  • Spring会在上下文中自动寻找,并自动给bean装配属性

spring中的是三种装配的方式

  • 在xml中显示的配置
  • 在java中显示配置
  • 隐式的自动装配bean(重要)

例:

1
2
3
4
5
6
<bean id="cat" class="service.cat" />
<bean id="dog" class="service.dog" />
<bean id="people" class="vo.people" autowire="byName">
<!--autowire="byName" 根据vo中的属性值,在xml寻找id相同的插入-->
<!--autowire="byType" 根据vo中的类型,在xml寻找相同的类型插入,有多个类型一致,则报错-->
</bean>

6、注解

  • 必须要导入aop包
  • 必须导入约束:context的约束
  • 重要: <context:annotation-config /> 开启注解支持,不要这个则空指针
1
@Nullable  字段标记了这个注解,说明这个字段可以为null

1、@Autowired

直接放属性上使用即可
使用后可以忽略set方法,前提是这个自动装配的属性在loc(spring.xml)容器中存在,且符合名字,byName的方式实现,如果找不到id 则通过byType实现,如果俩个都找不到则报错

例:xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!--包是从别的的配置中粘贴过来的,有些不需要的可以删除-->
<?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"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<!-- 开启注解支持 -->
<context:annotation-config />

<bean id="dog" class="service.dog"></bean>
<bean id="cat" class="service.cat"></bean>
<bean id="ren" class="vo.Ren"></bean>
</beans>

属性类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package vo;

import org.springframework.beans.factory.annotation.Autowired;

import service.cat;
import service.dog;

public class Ren {

private String name;

@Autowired(required = false)
@Qualifier(value="dog222")指定去xml中找id为dog222的
<!--required = false 说明这个属性可以为null, 为true 则不可以为无-->
private dog dog;

@Autowired
private cat cat;
}

测试

1
2
3
4
5
6
7
@Test
void test() {
ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
Ren ren = context.getBean("ren",Ren.class);
ren.getCat().cat();
ren.getDog().dog();
}

2、@Resource和@Autowired的区别

  • 都是自动装配的,都可以放在属性字段上
  • @Autowired通过找xml中的class类型实现,而且必须要这个对象存在
  • @Resource默认通过bynamed的方式实现,如果找不到则通过byType实现,如果俩个都找不到的情况下,就报错
  • 执行顺序不同:@Autowired通过byType的方式实现。@Resource默认通过byname的方式实现
  • @Qualifier通常配合@Resource来实现
  • @Qualifier可以指定一个id去匹配

2、使用注解开发

  • @Component:组件,放在类上,说明这个类被spring管理了,就是bean
  • 等价于
  • @Value(“值”) 给属性注值,也可以直接放set上面
  • 衍生的注解
    • @Component:有几个衍生注解,我们在web开发中,辉安装三层架构分层
    • dao层: @Repository
    • service层: @Service
    • controller层: Controller
    • 这四个注解功能一样,都是代表将某个类注册到Spring中装配bean
  • 作用域
    • @Scope(“singleton”)表示是单利模式,prototype为原型模式

例:

1
2
3
4
5
6
7
8
9
@Component
@Scope("prototype")
//等价于<bean id="user" class="dao.user">
public class User {
@Value("测试")
//<property name="name" value="测试"/>
public String name;
}

3、小结

  • xml与注解
    • ​ xml万能,可以用任意地方,方便简单
    • ​ 注解不是自己类使用不了,维护相对复杂
  • xml与注解最佳实践
    • xml用来管理bean
    • 注解只负责完成属性的注入

7、使用java实现配置

1
2
@Configuration // 放于类名上,代表一个配置类,相当于beans
@Bean//放于方法上,这个方法里面的返回值就相当于class,方法名相当于id

1
2
3
4
5
6
7
8
@Configuration //代表一个配置类,相当于beans
public class Stuent {
@Bean//这个方法里面的返回值就相当于class,方法名相当于id
//并且这个方法必须要有返回类型,否则会报类转换异常
public User getUser() {
return new User();
}
}

例:

1
2
3
ApplicationContext stu = new AnnotationConfigApplicationContext(Stuent.class);//读取注解的类名.class(相当于spring.xml)
Stuent s = (Stuent) stu.getBean("getUser"); //这里放的是方法名因为getUser返回为User,所以要强转为User
System.out.println(s);

8、代理模式

1、静态代理

  • 代理模式的好处:

    • 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
    • 公共也就交给了代理角色!实现了业务的分工!
    • 公共业务发生扩展的时候,方便集中管理!
  • 缺点:

    • 一个真实角色就会产生一个代理角色;代码量辉翻倍,开发效率会变低

2、动态代理

动态代理

动态代理test

9、AOP

1、什么是AOP

AOP(Aspect Oriented Programming):面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术,AOP是OOP的延续,是软件开发中的一个热底单,也是Spring框架中的一个重要内容,利用AOP可以对各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率

2、自定义记录类

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">

<bean id="jilu" class="mapper.jilu"></bean> <!--加载自定义记录类-->
<bean id="CRUD" class="service.Student"></bean> <!--记录操作类-->

<aop:config>
<aop:aspect ref="jilu"> <!--切入点-->
<aop:pointcut expression="execution(* service..*.*(..))" id="xx"/> <!--这是加载操作里面所有对的类和方法, 你可以可以指定-->
<aop:before method="first" pointcut-ref="xx"/> <!--method 的值是记录类对的方法名-->
<aop:after method="foot" pointcut-ref="xx"/>
</aop:aspect>
</aop:config>
</beans>

例:切面方法

1
2
3
4
5
6
7
public void first() {
System.out.println("记录开始");
}

public void foot() {
System.out.println("记录结束");
}

普通方法

1
2
3
public void add() {
System.out.println("添加");
}

测试

1
2
3
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Student stu=context.getBean("CRUD",Student.class);
stu.add();

3、接口记录类

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">

<bean id="jilu" class="mapper.jilu"></bean>
<bean id="jies" class="mapper.jies"></bean>
<bean id="CRUD" class="service.Student"></bean>

<aop:config>
<aop:pointcut expression="execution(* service..*.*(..))" id="xx"/>
<aop:advisor advice-ref="jilu" pointcut-ref="xx" />
<aop:advisor advice-ref="jies" pointcut-ref="xx" />
</aop:config>
</beans>

例:方法开始

1
2
3
4
5
6
7
8
9
public class jilu implements MethodBeforeAdvice{
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
//mothod要执行对象的方法
//args:执行方法中的参数
//target:目标对象
}
}

例:方法结束

1
2
3
4
5
6
7
8
9
10
11
public class jies implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行后");
//mothod要执行对象的方法
//args:执行方法中的参数
//target:目标对象
//returnValue:方法执行后返回的值
}

}

4、注解记录

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">

<bean id="zhix" class="mapper.zhix"></bean>
<bean id="CRUD" class="service.Student"></bean>
<aop:aspectj-autoproxy />
</beans>

例:切面类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Aspect
public class zhix {

@Before("execution(* service..*.*(..))")
public void first() {
System.out.println("方法开始执行");
}

@After("execution(* service..*.*(..))")
public void foot() {
System.out.println("方法执行完");

}
}

没有写的则是跟自定义中的一样

10、Spring和Mybits整合

例:springxml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?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="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/school"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>

<!-- 加载Mybatis第一与数据库建立连接,第二初始化mybatis里的配置-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath*:mapper/*.xml" />
</bean>

<bean id="userService" class="service.UserImpl">
<!--注入sqlSessionFactory-->
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
</beans>

mybatisxml

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="stu">
<select id="StudentAll" parameterType="vo.student" resultType="vo.student">
select * from student
</select>
</mapper>

实现类

1
2
3
4
5
6
7

<!--User为自己写的接口-->
public class UserImpl extends SqlSessionDaoSupport implements User{
public List<student> getList() {
return getSqlSession().selectList("StudentAll");
}
}

测试

1
2
3
4
5
6
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
User stu = (User) context.getBean("userService");
List<student> list = stu.getList();
for (student student : list) {
System.out.println(student);
}

属性类则与数据库中查出来的一一对应即可

第二种配置数据源方法

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<!--导入properties配置文件-->
<!--properties是键值对的形式-->
<context:property-placeholder location="classpath*:db.properties"/>

<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="${url}" />
<property name="username" value="${name}" />
<property name="password" value="${pass}" />
</bean>

db.properties

1
2
3
4
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/school
name=root
pass=123456

11、声明式事务

事务:要么全部成功,要么全部失败,不会执行一般就暂停失败了则会回滚

例:在spring.xml中添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 开启声明式事务 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" /><!-- 连接数据源 -->
</bean>

<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- 给那些方法配置事务,*则是所有方法 -->
<!--propagation="REQUIRED" 默认值,也可以不写 -->
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>

<!-- 配置事务切入 -->
<aop:config proxy-target-class="true">
<!-- 这是导入service包下的所有类,你也可以指定 -->
<aop:pointcut expression="execution(* service.*.*(..))" id="txPointCut" />
<aop:advisor pointcut-ref="txPointCut" advice-ref="txAdvice" />
</aop:config>

头部xml修改为

1
2
3
4
5
6
7
8
9
10
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">