欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring V4.2入门详解

程序员文章站 2022-05-29 14:41:38
...

震惊!原来Spring框架入门仅需这么几步

老营销号了????

Spring一学就忘是怎么回事呢?Spring相信大家都很熟悉,但是Spring一学就忘是怎么回事呢,下面就让小编带大家一起了解吧。
  Spring一学就忘,其实就是Spring超级恶心????,大家可能会很惊讶Spring怎么会一学就忘呢?但事实就是这样,小编也感到非常惊讶。
  这就是关于Spring一学就忘的事情了,大家有什么想法呢,欢迎在评论区告诉小编一起讨论哦!

教学开始

1.Spring的概述

1.1介绍

Spring–SE/EE开发的一站式框架,百度百科,学习SSH和SSM必走之路。

一站式框架:有EE开发的每一层解决方案。

1.2下载

下载地址

解压后的文件:

  • docs :Spring的开发规范和API
  • libs :Spring的开发的jar和源码
  • schema :Spring的配置文件的约束

1.3引入Spring核心jar包

Spring V4.2入门详解

1.4原始Dao存在的问题

原始Dao虽然可以通过接口实现多态,但是需要修改时还是需要修改源码

而好的程序需满足OCP原则:在尽量不修改程序源码的基础上对程序进行扩展

Spring V4.2入门详解

1.5IOC和DI

IOC:控制反转,将对象的创建权反转给了Spring。

DI:依赖注入,前提必须有IOC的环境,Spring管理这个类的时候将类的依赖的属性注入(设置)进来。

IOC实现需要DI,DI前提必须有IOC

2.Spring的配置

2.1头配置

在src下新建文件applicationContext.xml(名字任意,默认是这个)

这里把下文注解context约束,aop约束,事务tx约束都导入了

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">

这里可以通过解压目录下spring-framework-4.2.4.RELEASE\docs\spring-framework-reference\html\xsd-configuration.html查看需要的配置,也可以通过Design界面下先在Preference下输入cato配置xsd文件然后右键标签选择add添加约束

2.2标签的配置

id和name区别:id需要唯一却不能有特殊字符,name相反

Bean的作用范围的配置scope

singleton :默认的,Spring会采用单例模式创建这个对象。

prototype :多例模式。(Struts2和Spring整合一定会用到)

request,session,globalsession:应用在web项目中,分别存到各自的域,其中globalsession必须在porlet环境下使用。

porlet案例:登陆百度,然后进入百度的子页面如贴吧地图等不需要登陆了

2.3Spring的工厂类

BeanFactory :老版本的工厂类

ApplicationContext :新版本的工厂类,有两个实现类:

  • ClassPathXmlApplicationContext :加载类路径下的配置文件(相对于src)
  • FileSystemXmlApplicationContext :加载文件系统下的配置文件(绝对路径)

2.4Spring的实例化方式和属性注入

实例化方式:无参构造,静态/实例工厂实例化

属性注入:

set方法注入----name属性名,value属性值,ref关联其他类

P名称空间注入----p:name p:属性名

SpEL属性注入----#{‘xxx’}字符串 #{car}其他类 #{car.name}其他类的属性

<!-- 创建方式1:空参构造创建 -->
<bean name="user" class="com.heima.domain.User"> <!-- scope="singleton" init-method="init" destroy-method="destory" -->
    <!-- set方式注入 -->
    <!-- 值类型注入 -->
    <property name="username" value="tom"></property>
    <property name="age" value="18"></property>
    <!-- 引用类型注入:为car属性注入下方配置的car对象 -->
    <property name="car" ref="car"></property>
</bean>
<!-- 将car对象配置到容器中 -->
<bean name="car" class="com.heima.domain.Car">
    <property name="carname" value="BenCi"></property>
    <property name="color" value="white"></property>
</bean>

<!-- 构造函数注入
  name:参数名,index:参数索引,type:参数类型
  -->
<bean name="user4" class="com.heima.domain.User">
    <constructor-arg name="username" index="0" type="java.lang.Integer" value="555"></constructor-arg>
    <constructor-arg name="car" ref="car" index="1"></constructor-arg>
</bean>


<!-- 复杂类型注入 -->

<bean name="cb" class="com.heima.domain.CollectionBean">
    <!-- array注入 -->
    <property name="arr">
        <array>
            <value>tom</value>
            <value>jack</value>
            <ref bean="car"/>
        </array>
    </property>
    <!-- list注入和array差不多 -->
    <!-- map类型注入 -->
    <property name="map">
        <map>
            <entry key="url" value="jdbc:mysql:///crm"></entry>
            <entry key="user" value-ref="user4"></entry>
        </map>
    </property>
    <!-- properties类型注入 -->
    <property name="properties">
        <props>
            <prop key="driverClass">com.jdbc.mysql.Driver</prop>
            <prop key="username">root</prop>
            <prop key="password">root</prop>
        </props>
    </property>
</bean>

<!-- 创建方式2:静态工厂创建
   调用UserFactory的createUser方法创建名为user2的对象放入容器
  -->
<bean name="user2" class="com.heima.domain.UserFactory" factory-method="createUser"></bean>

<!-- 创建方式3:实例构造创建 -->
<bean name="user3" factory-bean="userFactory" factory-method="createUser2"></bean>
<bean name="userFactory" class="com.heima.domain.UserFactory"></bean>

2.5分模块开发

把applicationContext.xml拆分成各司其职的模块,然后通过

<!-- 导入其他spring配置文件,文件位置:相对于src -->
<!-- <import resource=""/> -->

2.6Spring整合Junit

在测试类上面添加如**解

@RunWith(SpringJUnit4ClassRunner.class)//帮我们创建容器
//指定创建容器时使用哪个配置文件
@ContextConfiguration("classpath:applicationContext.xml")

3.IOC的注解

3.1添加约束

注解约束是context(上文以添加)

3.2配置注解扫描

<!-- 指定扫描com.heima.domain包下所有类(包括子孙包)的所有注解 -->
<context:component-scan base-package="com.heima.domain"></context:component-scan>

3.3在相关类上添加注解

@Component("user")//相当于<bean name="user" class="com.heima.domain.User">
//@Service("user")//service层
//@Controller("user")//web层
//@Repository("user")//dao层

3.4属性注入的注解

使用注解注入的方式,可以不用提供 set 方法

@Value() 注入普通类型

@Autowired 自动装配(默认按类型进行装配 ),如果有多个同类型的,必须要和@Autowired强制使用名称注入一起使用

@Resource(name=“xxx”) 作用相当于@aaa@qq.com

3.5XML和注解的整合开发

Bean 有 XML 配置.但是使用的属性使用注解注入

<!-- 扫描是为了扫描类上的注解(class) -->
<!-- <context:component-scan base-package="com.heima.domain"></context:component-scan> -->
<!-- 在没有扫描的情况下,使用属性注入的注解**@Resource**@**Value()**-->
<context:annotation-config/>

4.AOP的开发

4.1AOP的概念

百度百科,AOP 最早由 AOP 联盟的组织提出的,制定了一套规范.Spring 将 AOP 思想引入到框架中,必须遵守 AOP 联盟的规范.

Spring现在使用的AOP开发方式是基于AspectJ

4.2AOP的底层实现

JDK 的动态代理 :针对实现了接口的类产生代理.
Cglib 的动态代理 :针对没有实现接口的类产生代理. 应用的是底层的字节码增强的技术 生成当前类
的子类对象

4.3AOP的相关术语

Spring V4.2入门详解

4.4Spring 使用 AspectJ 进行 AOP 的开发:XML 的方式

4.4.1导包

com.springsource.org.aopalliance-1.0.0.jar(AOP 联盟)
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar(AspectJ)
spring-aop-4.2.4.RELEASE.jar
spring-aspects-4.2.4.RELEASE.jar(Spring 整合AspectJ)

4.4.2约束

引入约束aop(前文已经导过,为了方便,后文配置又写了一下)

4.4.3目标对象
package com.heima.service.impl;

import com.heima.service.UserService;

public class UserServiceImpl implements UserService{

	@Override
	public void save() {
		System.out.println("保存用户");
	}

	@Override
	public void find() {
		System.out.println("查找用户");
	}

	@Override
	public void delete() {
		System.out.println("删除用户");
	}

	@Override
	public void update() {
		System.out.println("更新用户");
	}	
}
4.4.4通知对象
package com.heima.springaop;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyAdvice {
	//前置通知 -|目标方法运行前调用
	public void before() {
		System.out.println("这是前置通知");
	}
	//后置通知(如果出现异常不会调用) -|目标方法运行后调用
	public void afterReturning(Object result) {
		System.out.println("这是后置通知(如果出现异常不会调用)"+result);
	}
	//环绕通知 -|在目标方法之前之后都调用
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("这是环绕之前的部分");
		Object proceed = pjp.proceed();
		System.out.println("这是环绕之后的部分");
		return proceed;
	}
	//异常拦截通知 -|如果出现异常就会调用
	public void afterException(Throwable ex) {
		System.out.println("出现异常了"+ex.getMessage());
	}
	//最终通知(无论是否出现异常都会调用)
	public void after() {
		System.out.println("这是后置通知(无论是否出现异常都会调用)");
	}
}
4.4.5配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">

<!-- 导入aop(约束)命名空间 -->
<!-- 1.配置目标对象 -->
	<bean name="userService" class="com.heima.service.impl.UserServiceImpl"></bean>
<!-- 2.配置通知对象 -->
	<bean name="myAdvice" class="com.heima.springaop.MyAdvice"></bean>
<!-- 3.配置将通知织入目标对象 -->
	<aop:config>
		<!-- 配置切入点
			public void com.heima.service.impl.UserServiceImpl.save()
			void com.heima.service.impl.UserServiceImpl.save()
			* com.heima.service.impl.UserServiceImpl.save()
			* com.heima.service.impl.UserServiceImpl.*()
			
			* com.heima.service.impl.*ServiceImpl.*(..)
			* com.heima.service.impl..*ServiceImpl.*()
		 -->
		<aop:pointcut expression="execution(* com.heima.service.impl.*ServiceImpl.*(..))" id="pc"/>
		<aop:aspect ref="myAdvice">
			<!-- 指定名为xxx的方法作为xxx通知 -->
			<aop:before method="before" pointcut-ref="pc"/>
			<aop:after-returning method="afterReturning" pointcut-ref="pc"  returning="result"/>
			<aop:around method="around" pointcut-ref="pc"/>
			<aop:after-throwing method="afterException" pointcut-ref="pc" throwing="ex"/>
			<aop:after method="after" pointcut-ref="pc"/>
		</aop:aspect>
	</aop:config>
</beans>

5.AOP的注解

5.1打开注解配置

<!-- 在配置文件中打开注解aop的开发 -->
<aop:aspectj-autoproxy/>

5.2注解的AOP的通知类型

@Before :前置通知

@AfterReturning :后置通知

@Around :环绕通知

@AfterThrowing :异常抛出通知

@After :最终通知

5.3AOP的注解切入点的配置

@Pointcut(value="execution(xxxx)")
	public void pointcut1(){}

之后注解就可以简化为

@Before(value=“类名称.pointcut1”)

6.Spring的JDBC模板

Spring是EE开发的一站式的框架,有EE开发的每层的解决方案。Spring对持久层也提供了解决方案:ORM模块和JDBC的模板。

6.1导包

mysql-connector-java-5.1.7-bin.jar
spring-jdbc-4.2.4.RELEASE.jar
spring-tx-4.2.4.RELEASE.jar

6.2创建db.properties

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///heima
jdbc.user=root
jdbc.password=root

6.3配置

<!-- 指定spring读取db.properties配置 -->
<context:property-placeholder location="classpath:db.properties"/>

<!-- 将c3p0连接池放入spring容器 -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${jdbc.driverClass}"></property>
    <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
    <property name="user" value="${jdbc.user}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 将JDBCTemplate放入spring容器 -->
<!-- <bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
 <property name="dataSource" ref="dataSource"></property>
</bean>  -->
<!-- 将TeaDao放入spring容器 -->
<bean name="teaDao" class="com.heima.jdbctemplate.TeaDaoImpl">
    <!-- <property name="jt" ref="jdbcTemplate"></property> -->
    <property name="dataSource" ref="dataSource"></property>
</bean>

6.4模板的CRUD操作

@Override
public void save(Tea t) {
    String sql = "insert into tea values(null,?)";
    super.getJdbcTemplate().update(sql,t.getName());
}

@Override
public void delete(int id) {
    String sql = "delete from tea where id = ?";
    super.getJdbcTemplate().update(sql,id);
}

@Override
public void update(Tea t) {
    String sql = "update tea set name=? where id=?";
    super.getJdbcTemplate().update(sql,t.getName(),t.getId());
}

@Override
public Tea getById(int id) {
    String sql = "select * from tea where id=?";
    return super.getJdbcTemplate().queryForObject(sql, new RowMapper<Tea>() {

        @Override
        public Tea mapRow(ResultSet rs, int arg1) throws SQLException {
            Tea t = new Tea();
            t.setId(rs.getInt("id"));
            t.setName(rs.getString("name"));
            return t;
        }

    }, id);
}

@Override
public int getTotalCount() {
    String sql = "select count(*) from tea";
    return super.getJdbcTemplate().queryForObject(sql, Integer.class);
}

@Override
public List<Tea> getAll() {
    String sql = "select * from tea";
    List<Tea> list = super.getJdbcTemplate().query(sql, new RowMapper<Tea>() {

        @Override
        public Tea mapRow(ResultSet rs, int arg1) throws SQLException {
            Tea t = new Tea();
            t.setId(rs.getInt("id"));
            t.setName(rs.getString("name"));
            return t;
        }

    });
    return list;
}

模板不提供类似于dbutils的各种rowmapper,需要自己写

7.Spring的事务管理

7.1API

latformTransactionManager:平台事务管理器

​ ---- DataSourceTransactionManager:底层使用JDBC管理事务

TransactionDefinition :事务定义信息

TransactionStatus:事务的状态

7.2事务的传播行为propagation

  • PROPAGATION_REQUIRED:默认值,如果A中有事务,使用A中的事务,如果A没有,创建一个新的事务,将操作包含进来
  • PROPAGATION_REQUIRES_NEW:如果A中有事务,将A的事务挂起(暂停),创建新事务,只包含自身操作。如果A中没有事务,创建一个新事务,包含自身操作。
  • PROPAGATION_NESTED:嵌套事务,如果A中有事务,按照A的事务执行,执行完成后,设置一个保存点,执行B中的操作,如果没有异常,执行通过,如果有异常,可以选择回滚到最初始位置,也可以回滚到保存点。

7.3搭建环境

Dao层

@Override
public void addMoney(int id, double money) {
    super.getJdbcTemplate().update("update account set money = money+? where id=?",money,id);	
}

@Override
public void reduceMoney(int id, double money) {
    super.getJdbcTemplate().update("update account set money = money-? where id=?",money,id);	
}

Service层

private AccountDao ad;

public void setAd(AccountDao ad) {
    this.ad = ad;
}

@Override
public void tansfer(int from, int to, double money) {
    ad.reduceMoney(from, money);
    //		int i=1/0;
    ad.addMoney(to, money);
}

xml配置

<!-- 指定spring读取db.properties配置 -->
<context:property-placeholder location="classpath:db.properties"/>

<!-- 将连接池放入spring容器 -->
 <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
 	<property name="driverClass" value="${jdbc.driverClass}"></property>
    <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
    <property name="user" value="${jdbc.user}"></property>
    <property name="password" value="${jdbc.password}"></property>
  </bean>

 <!-- 将Dao放入spring容器 -->
 <bean name="accountDao" class="com.heima.dao.impl.AccountDaoImpl">
   <property name="dataSource" ref="dataSource"></property>
 </bean>
 <!-- service -->
 <bean name="accountService"class="com.heima.service.impl.AccountServiceImpl">
 	<property name="ad" ref="accountDao"></property>
 </bean>

测试代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:com/heima/transaction/applicationContext.xml")
public class Demo {
@Resource(name="accountService")
private AccountService as;

@Test
public void fun1() {
as.tansfer(1, 2, 100);
}
}

7.4编程式事务(需要手写代码)

太过麻烦而且基本使用,略过

7.5声明式事务管理(通过配置实现)

<!-- 事务核心管理器,封装了所有事务事件,依赖于连接池 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
	<tx:attributes>
		<!-- 以方法为单位,指定方法用什么事务属性
			isolation:隔离级别
			propagation:传播行为
			read-only:是否只读
		 -->
		<tx:method name="tansfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
		<tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
		<tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
		<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
		<tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
		<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
		<tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
		<tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/>
		<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/>
	</tx:attributes>
</tx:advice>

<!-- 配置织入 -->
<aop:config>
	<!-- 配置切点表达式 -->
	<aop:pointcut expression="execution(* com.heima.service.impl.*ServiceImpl.*(..))" id="txPc"/>
	<!-- 配置切面:通知+切点
		advice-ref:通知的名称		pointcut-ref:切点的名称
	 -->
	 <aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"/>
</aop:config>

7.6注解方式的声明式事务管理

<!-- 开启使用注解管理aop事务 -->
<tx:annotation-driven/>
@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
public void tansfer(int from, int to, double money) {
    ad.reduceMoney(from, money);
    //		int i=1/0;
    ad.addMoney(to, money);
}

结语

没错吧,Spring入门真的只需要掌握这么亿点点,真的一点都不♂,我真的不会忘????

哎,你是不是觉得我很菜,是不是觉得我连白银都打不过。从现在开始,我将一次不死,并且超神给你看。

芜湖!起飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞!!!!!!!!!!

明式事务管理

<!-- 开启使用注解管理aop事务 -->
<tx:annotation-driven/>
@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
public void tansfer(int from, int to, double money) {
    ad.reduceMoney(from, money);
    //		int i=1/0;
    ad.addMoney(to, money);
}

结语

没错吧,Spring入门真的只需要掌握这么亿点点,真的一点都不♂,我真的不会忘????

哎,你是不是觉得我很菜,是不是觉得我连白银都打不过。从现在开始,我将一次不死,并且超神给你看。

芜湖!起飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞!!!!!!!!!!