Spring框架的目标是使j2EE开发变得更容易使用,通过启用基于POJO编程模型来促进良好的编程实践
spring理念:使现有的技术更加容易使用,解决企业应用开发的复杂性
总结:Spring是一个轻量级的控制反转(IOC),面向切面编程(AOP)的框架!

spring主要由例如以下几个模块构成
Spring Framework 开发应用程序时,Spring 对应用程序本身的结构影响非常小。对领域模型可以做到零污染;对功能性组件也只需要使用几个简单的注解进行标记,完全不会破坏其原有结构,反而能将组件结构进一步简化。这就使得基于Spring Framework 开发应用程序时结构清晰、简洁优雅。Inversion of Control,翻转资源获取方向。把自己创建资源、向环境索取资源变成环境将资源准备好,我们享受资源注入。Aspect Oriented Programming,在不断修改源代码的基础上增强代码功能。Spring Framework 的基础上全部使用Spring来实现。总结:控制,其实就是由Spring来管理对象,创建对象。反转,其实就是从主动获取对象,变为被动获取对象的过程。
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.3.22version>
dependency>
dependencies>
在pojo包下创建一个user的类
<bean id="user" class="com.cczj.pojo.user">
<constructor-arg index="0" value="第一个属性的值"/>
bean>
<bean id="user" class="com.cczj.pojo.user">
<constructor-arg type="java.lang.String" value="类型为String的值"/>
bean>
<bean id="user" class="com.cczj.pojo.user">
<constructor-arg name="name" value="name属性的值"/>
bean>
总结:在配置spring文件被加载的时候,该容器中的对象就已经被创建了,在之后调用的过程中,该对象不会重新创建。
将bean的ID进行起别名的操作,如果添加了别名,也可以通过别名来获取对象
<bean id="user" class="com.cczj.pojo.user">
<constructor-arg name="name" value="name属性的值"/>
bean>
<alias name="user" alias="userNew"/>
在getBean 操作时,可以使用别名来获取!
id: bean的唯一标识符,也就是相当于我们学的对象名
class: bean对象所对应的全限定名:包名 + 类名
name: 别名,可以取多个别名
导入多个spring-xml文件,将这些文件进行合并。合并之后,在使用时只需要获取总的文件就可以
以上写过
在pojo中创建类,用来测试注入
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;
}
各种数据类型用于注入的方式—> 以Student类为模板
<bean id="address" class="com.cczj.spring.pojo.Address"/>
<bean id="student" class="com.cczj.spring.pojo.Student">
<property name="name" value="名称"/>
<property name="address" ref="address"/>
<property name="books">
<array>
<value>红楼梦value>
<value>三国演义value>
<value>西游记value>
<value>水浒传value>
array>
property>
<property name="hobbies">
<list>
<value>听歌value>
<value>打游戏value>
<value>学DPvalue>
list>
property>
<property name="card">
<map>
<entry key="身份证" value="312344198310345573"/>
<entry key="银行卡" value="21312489779129321938912"/>
map>
property>
<property name="games">
<set>
<value>LOLvalue>
<value>COCvalue>
<value>BOBvalue>
set>
property>
<property name="wife">
<null/>
property>
<property name="info">
<props>
<prop key="学号">314143252prop>
<prop key="班级">java班prop>
<prop key="性别">男prop>
props>
property>
bean>
两种命名空间的注入方式
<bean id="address" class="com.cczj.spring.pojo.Address" p:name="张三" p:gender="男"/>
<bean id="address2" class="com.cczj.spring.pojo.Address" c:name="张三" c:gender="女"/>
注意点:p命名和c命名不能直接导入,需要引入约束 (IDE中可以自动导入)
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
<bean id="address" class="com.cczj.spring.pojo.Address" p:name="张三" p:gender="男" scope="singleton"/>
scope的默认为单例模式
<bean id="address" class="com.cczj.spring.pojo.Address" p:name="张三" p:gender="男" scope="prototype"/>
每次getBean的时候都会产生新对象
自动装配是Spring满足bean依赖的一种方式
Spring会在上下文中自动寻找,并且自动给bean装配属性~
在Spring 中有三种装配的方式
byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的 bean id
byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean
总结:
使用byName的时候,需要保证所有的bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致
使用byType的时候,需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性的类型一致
提示:
jdk 1.5版本支持注解、spring 2.5支持注解
要使用注解须知:
context 约束Autowired 可以不用编写set方法,前提是这个自动装配在IOC(spring)容器中存在,且符合名字byName(唯一)Autowired注解实现装配(有多个类型的时候,因为Autowired默认是通过byType来进行装配的)可以用Qualifier(value="name") 注解转换为使用byName来进行装配@Resource 和 @Autowired 的区别:
byType的方式实现,而且必须要求这个对象存在!【常用】byName的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就报错!【常用】 (注:JDK 11 之后将这个注解取消了)在spring4之后,若使用注解开发,必须要保证aop的包导入了
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G77Qd3Q1-1662555223730)(后端框架.assets/image-20220906183737130.png)]](https://1000bd.com/contentImg/2023/11/04/164415336.png)
使用注解需要导入 context 约束,增加注解的支持
获取Bean的三种方式
- 根据Bean的ID获取
- 根据Bean的类型获取
- 根据Bean的类型和ID获取 (常用)
@Test
public void testSpringIOC() {
// -- 获取IOC容器
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
// -- 根据Bean的Id获取Bean
// Student bean = (Student) ioc.getBean("studentOne");
// -- 根据Bean的类型来获取Bean
// Student bean = ioc.getBean(Student.class);
// -- 根据Bean的类型和ID来获取指定的Bean
Student bean = ioc.getBean("studentOne", Student.class);
System.out.println(bean);
}
@Component
public class User {
@Value("cczj")
private String name;
@Override
public String toString() {
return "Hello{" +
"name='" + name + '\'' +
'}';
}
}
@Component 有几个衍生注解,我们在web开发中,会按照mvc三层架构分层~
这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配Bean
@scope(“prototype”)
xml 与 注解
xml与注解最佳实践
<context:component-scan base-package="com.cczj.spring"/>
<context:annotation-config/>
我们可以完全不适用Spring的xml配置,全部交给java来做
javaConfig 是 Spring的一个子项目,在Spring4之后,他成为了一个核心功能!
@Component
public class User {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void show() {
System.out.println("Hello" + name);
}
@Override
public String toString() {
return "Hello{" +
"name='" + name + '\'' +
'}';
}
}
// -- @Configuration 代表这是一个配置类,和我们之前配置的 beans.xml 相同
@Configuration
@ComponentScan("com.cczj.pojo") // --开启扫描
public class JavaImplXml {
// -- 注册一个bean 相当于之前写的一个bean标签
// 这个方法的名字就相当于bean标签中的Id属性
// 这个方法的返回值就相当于bean标签中的class属性
@Bean
public User getUser() {
return new User(); // 返回需要注入的对象
}
}
public class MyTest {
@Test
public void test() {
ApplicationContext context = new AnnotationConfigApplicationContext(JavaImplXml.class);
User user = context.getBean("getUser", User.class);
System.out.println(user);
}
}
AOP(Aspect Oriented Programming)是一种设计思想,是软件设计领域中的面向切面编程,它是面向对象编程的一种补充和完善,它以通过预编译方式和运行期动态代理方式实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术。
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
<version>5.3.22version>
dependency>
@Aspect // -- 标注这个类是一个切面
public class AnnotationPointCut {
// -- 设置公共切入点
@Pointcut("execution(* com.cczj.service.impl.*.*(..))")
public void pointCut() {
}
@Before("pointCut()")
public void before() {
System.out.println("方法执行前~~~~");
}
@After("pointCut()")
public void after() {
System.out.println("方法执行后~~~~");
}
// -- 在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
@Around("pointCut()")
public void around(ProceedingJoinPoint jp) throws Throwable {
System.out.println("环绕前~~");
// -- 获得方法签名
Signature signature = jp.getSignature();
System.out.println("signature = " + signature);
// -- 执行方法
Object proceed = jp.proceed();
System.out.println("环绕后~~");
System.out.println(proceed);
}
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EXUjDWQx-1662555223730)(后端框架.assets/image-20220907173355613.png)]](https://1000bd.com/contentImg/2023/11/04/164415298.png)
// -- 在切面中,需要通过指定的注解将方法标识为通知方法
@Pointcut("execution(* com.cczj.spring.aop.*.*(..))")
public void pointCut() {
}
@Before("pointCut()") // 等同于下方Before
// @Before("execution(public double com.cczj.spring.aop.CalculatorImpl .add(double, double))")
@Before("execution(* com.cczj.spring.aop.*.*(..))")
表示包下任何访问修饰符 任何返回值 任何的类中的所有方法的所有参数
@AfterReturning(value="pointCut()", returning="result")
将接收方法的返回值设置为result
@AfterThrowing(value="pointCut()", throwing="e")
接收目标方法发生的异常信息
<aop:config>
<aop:pointCut id="pointCut" expression="expression(* com.cczj.spring.aop.*.*(..))">
aop:pointCut>
<aop:advisor advice-ref="log" pointCut-ref="pointCut"/>
<aop:advisor advice-ref="afterlog" pointCut-ref="pointCut"/>
aop:config>
<bean id="diy" class="com.cczj.diy.DiyPointCut"/>
<aop:config>
<aop:aspect ref="diy">
<aop:pointCut id="point" expression="expression(* com.cczj.service.xxxServiceImpl.*(..))"/>
<aop:before method="before" pointCut-ref="point"/>
<aop:before method="after" pointCut-ref="point"/>
aop:aspect>
aop:config>
步骤:
编写spring.xml,将mybatis部分配置整合在spring.xml中
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.cczj.ssm">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
context:component-scan>
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.cczj.ssm.pojo"/>
bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.cczj.ssm.mapper"/>
bean>
beans>
事务的ACID原则:
<tx:advice id="txAdvice" transcation-manager="transcationManager">
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="query" propagation="REQUIRED"/>
tx:attributes>
tx:advice>
<aop:config>
<aop:pointCut id="txPointCut" expression="expression(* com.cczj.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointCut-ref="txPointCut"/>
aop:config>
在声明式事务中,要配置一个切面,其中就用到了propagator,其中propagation一共有七种配置
REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 (默认)[常用]SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。 NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。 NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。开启事务的注解驱动
<tx:annotation-driven />
@Transactional 注解标识在类中,效果为全类开启事务。标识在方法中,效果为这个方法开启事务
事务属性:
@Transactional(readOnly = true) 只允许查看,不允许修改@Transactional(timeout = 3) 避免程序运行bug浪费数据库资源,提前关闭并回滚@Transactional(noRollbackFor = ?) 选择回滚的异常情况。可以选择异常情况下进行回滚,也可以选择除了该异常情况下都回滚@Transactional(isolation = Isolation.DEFAULT)