1 Spring介绍:
Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将 面向接口的编程思想贯穿整个系统应用。
一句话概括:
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。
1.1特点:
1.方便解耦,简化开发(通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,)
2 AOP面向切面编程支持
3 声明式实物支持
4方便程序测试
5 方便集成各种优秀框架
1.2组织架构
ORM- object relation mapping
OXM - Object xml mappingJMS - Java 消息服务( Java Message Service , JMS )WebSocket protocol 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信 (full-duplex) 。一 开始的握手需要借助HTTP 请求完成。 Socket 是传输控制层协议, WebSocket 是应用层协议。Portlet 是一种 Web 组件-就像 servlets -是专为将合成页面里的内容聚集在一起而设计的。通常请求一 个portal 页面会引发多个 portlets 被调用。每个 portlet 都会生成标记段,并与别的 portlets 生成的标记段 组合在一起嵌入到portal 页面的标记内
1.3spring核心模块
- spring-core:依赖注入IOC与DI的最基本实现
- spring-beans : Bean 工厂与 bean 的装配- spring-context : spring 的 context 上下文即 IoC 容器- spring-context-support- spring-expression : spring 表达式语言
2.spring中的IOC
IOC是 Inverse of Control 的简写,意思是控制反转。是降低对象之间的耦合关系的设计思想。
DI 是 Dependency Injection 的缩写,意思是依赖注入 , 说的是创建对象实例时,同时为这个对象注入它 所依赖的属性
2.1配置:
<!-- Spring的核心工具包-->
<dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.0.8.RELEASE</version></dependency><!--在基础IOC功能上提供扩展服务,还提供许多企业级服务的支持,有邮件服务、任务调度、远程访问、缓存以及多种视图层框架的支持--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.8.RELEASE</version></dependency><!-- Spring IOC的基础实现,包含访问配置文件、创建和管理bean等 --><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>5.0.8.RELEASE</version></dependency><!-- Spring context的扩展支持,用于MVC方面 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>5.0.8.RELEASE</version></dependency><!-- Spring表达式语言 --><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>5.0.8.RELEASE</version></dependency>
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"></beans>
2.3 对象创建的方式
public class User {private String name; public User() {System.out.println("user无参构造方法");}public void setName(String name) {this.name = name;}public void show(){System.out.println("name="+ name );} }-------------------------------------------------------------<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="user" class="com.zx.pojo.User"><property name="name" value="zx"/></bean></beans>
public class UserT {private String name; public UserT(String name) {this.name = name;}public void setName(String name) {this.name = name;}public void show(){System.out.println("name="+ name );} }-------------------------------------------------------------
<!-- 第一种根据index参数下标设置 --><bean id="userT" class="com.zx.pojo.UserT"><!-- index指构造方法 , 下标从0开始 --><constructor-arg index="0" value="zhangsan"/></bean><!-- 第二种根据参数名字设置 --><bean id="userT" class="com.zx.pojo.UserT"><!-- name指参数名 --> <constructor-arg name="name" value="kuangshen2"/></bean><!-- 第三种根据参数类型设置 --><bean id="userT" class="com.zx.pojo.UserT"><constructor-arg type="java.lang.String" value="kuangshen2"/></bean>
public Person(String name , Car car){this.name = name;this.car = car;System.out.println("Person 的有参构造方法 :"+name+car);}<bean name="person" class="com.zx.spring.bean.Person"><constructor-arg name="name" value="rose"/><constructor-arg name="car" ref="car"/></bean>
public class PersonFactory {public static Person createPerson(){System.out.println(" 静态工厂创建 Person");return new Person();}}-------------------------------------------------------------<bean name="pf" class="com.xzk.PersonFactory" factory-method="createPerson" />
public class Users{public Person createPerson1(){System.out.println(" 非静态工厂创建 Person");return new Person();}}-------------------------------------------------------------<bean id="u2" class="com.bean.Users"></bean><bean id="u3" factory-method="createPerson1" factory-bean="u2"></bean>
1 )根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean 。2 )利用依赖注入完成 Bean 中所有属性值的配置注入。3 )如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。4 )如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂 实例的引用。5 )如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法 传入当前 ApplicationContext 实例的引用。6 )如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化方法 postProcessBeforeInitialzation() 对 Bean 进行加工操作,此处非常重要, Spring 的 AOP 就是利用它 实现的。7 )如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法。初始化 bean的时候执行,可以针对某个具体的 bean 进行配置。 afterPropertiesSet 必须实现 InitializingBean 接口。实现 InitializingBean 接口必须实现 afterPropertiesSe 方法。8 )如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。9 )如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization()。此时, Bean 已经可以被应用系统使用了。10 )如果在 中指定了该 Bean 的作用范围为 scope="singleton" ,则将该 Bean 放入 Spring IoC 的缓 存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 中指定了该 Bean 的作用范围为 scope="prototype",则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期, Spring 不再管理该 Bean。11 )如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁;如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方 法对 Bean 进行销毁。
<!--设置别名:在获取Bean的时候可以使用别名获取--><alias name="userT" alias="userNew"/>
3.DI注入值
分类:一种是调取属性的set方法赋值,第二种使用构造方法赋值
3.1 set注入值
1 基本属性类型值注入
<property name="name" value="jeck" />
2 引用属性类型值注入(对象)<property name="car" ref="car"></property>
3.2 构造注入:
public Person(String name , Car car){this.name = name;this.car = car;System.out.println("Person 的有参构造方法 :"+name+car);}--------------------------------------------------------------------------------------<bean name="person" class="com.zx.spring.bean.Person"><constructor-arg name="name" value="rose"/><constructor-arg name="car" ref="car"/></bean>
3.2.2 可以通过index属性,按照参数索引注入
<bean name="person2" class="com.zx.spring.bean.Person">
<constructor-arg name="name" value="helen" index="0"></constructor-arg><constructor-arg name="car" ref="car" index="1"></constructor-arg></bean>
3.2.3 使用type注入
public Person(Car car, String name) {
super();System.out.println("Person(Car car, String name)");this.name = name;this.car = car;}public Person(Car car, Integer name) {
super();System.out.println("Person(Car car, Integer name)");this.name = name + "";this.car = car;}<bean name="person2" class="com.xzk.spring.bean.Person"><constructor-arg name="name" value="988" type="java.lang.Integer" ></constructor-arg><constructor-arg name="car" ref="car" ></constructor-arg></bean>
3.3spel spring表达式(#)
<bean name="car" class="com.zx.spring.bean.Car" >
<property name="name" value="mime" /><property name="color" value=" 白色 "/></bean><!-- 利用 spel 引入 car 的属性 --><bean name="person1" class="com.xzk.spring.bean.Person" p:car-ref="car"><property name="name" value=" # {car.name}"/><property name="age" value=" # {person.age}"/></bean>
3.4 p命名空间注入值
xmlns:p="http://www.springframework.org/schema/p"---------------------------------------------------<bean id="u6" class="com.entity.Users" p:age="30" p:name=" 李四 " p:student- ref="stu1"></bean>
3.5 复杂类型注入
<!-- 数组变量注入 -->
<property name="arrs"><list><value>数组1</value><!--引入其他类型--><ref bean="car"/></list></property><!-- 集合变量赋值--><property name="list"><list><value>集合1</value><!--集合变量内部包含集合--><list><value>集合中的集合1</value><value>集合中的集合2</value><value>集合中的集合3</value></list><ref bean="car" /></list></property><!--map赋值 --><property name="map"><map><entry key="car" value-ref="car" /><entry key="name" value="保时捷" /><entry key="age" value="11"/></map></property><!-- properties赋值 --><property name="properties"><props><prop key="name">pro1</prop><prop key="age">111</prop></props></property>
3.6 自动注入(由程序自动给属性赋值)
autowire :no 不自动装配 ( 默认值 )byName 属性名 =id 名 ,调取 set 方法赋值byType 属性的类型和 id 对象的类型相同,当找到多个同类型的对象时报错,调取 set 方法赋值constructor 构造方法的参数类型和 id 对象的类型相同 , 当没有找到时,报错。调取构造方法赋值示例 :<bean id="service" class="service.impl.UserServiceImpl" autowire="constructor"></bean>配置全局自动装配 :<beans default-autowire="constructor/byName/byType/no">
4.注解实现IOC
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd
(2)配置注解扫描:指定扫描包下所有类中的注解,扫描包时,会扫描包所有的子孙包
<!--扫描包设置-->
<context:component-scan base-package="com.xzk.spring.bean"></context:component-scan>
(3)注解
3.1 添加在类名上
@Component("对象名")
@Service("person") // service 层@Controller("person") // controller 层@Repository("person") // dao 层@Scope(scopeName="singleton") // 单例对象@Scope(scopeName="prototype") // 多例对象
@Value("属性值")
private String name;
@Autowired // 如果一个接口类型,同时有两个实现类,则报错,此时可以借助 @Qualifier("beanname")@Qualifier("bean name")private Car car;// 说明 :@Resource 是 java 的注释 , 但是 Spring 框架支持 , @Resource指定注入哪个名称的对象//@Resource(name=" 对象名") == @Autowired + @Qualifier("name")@Resource(name="baoma")private Car car;
3.3 添加在方法上
@PostConstruct //等价于init-method属性
public void init(){System.out.println(" 初始化方法 ");}@PreDestroy // 等价于 destroy-method 属性public void destroy(){System.out.println(" 销毁方法 ");}
5.Aop介绍
AOP(Aspect Oriented Programming)即面向切面编程。即在不改变原程序的基础上为代码段增加新 的功能。应用在权限认证、日志、事务。
AOP 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
<dependency><groupId>aopalliance</groupId><artifactId>aopalliance</artifactId><version>1.0</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.13</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.0.8.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.0.8.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.0.8.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.8.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>5.0.8.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>5.0.8.RELEASE</version></dependency>
xmlns:aop="http://www.springframework.org/schema/aop"http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.2.xsd
<!--1. 创建目标类对象 --><bean name="userService" class="com.xzk.spring.service.UserServiceImpl" /><!--2. 配置增强类对象 --><bean name="myAdvice" class="com.xzk.spring.aop.MyAdivce" /><!-- 3. 配置将增强 织入 目标对象 --><aop:config><aop:pointcut id="pc" expression="execution(* com.xzk.spring.service.ServiceImpl.*.* (..))"/><aop:aspect ref="myAdvice"><aop:before method="before" pointcut-ref="pc" /><aop:after-returning method="afterReturning" pointcut-ref="pc" /><aop:around method="around" pointcut-ref="pc" /><aop:after-throwing method="afterException" pointcut-ref="pc" /><aop:after method="after" pointcut-ref="pc" /> </aop:aspect></aop:config>
System.out.println(" 切入点对象 :"+jp.getTarget().getClass().getSimpleName());System.out.println(" 切入点方法: "+jp.getSignature());System.out.println(" 切入点的参数: "+jp.getArgs()[0]);
<context:component-scan base-package="com.zx"></context:component-scan>
<aop:aspectj-autoproxy/>
@Pointcut("execution(* com.*.*(..))")public void anyMethod( ){//可以为空方法体}
@Pointcut("execution(* com.*.*(..))")public void anyMethod(){}@Before("anyMethod()")public void log(JoinPoint){System.out.println("myAspect....log....before");}@Around("anyMethod()")public void aroundTest(ProceedingJoinPoint pjp){System.out.println("around...before....");try {pjp.proceed();// 执行目标方法} catch (Throwable e) {e.printStackTrace();}System.out.println("around...after....");}
6.Spring事务管理
6.1什么是事务(Transaction)
通过 sql 将逻辑相关的一组操作绑定在一起,以便服务器 保持数据的完整性 ( 准确性 ) 。事务通常是以 begin transaction 开始,以 commit 或 rollback 结束。事务执行的流程 : 开启事务 -> 执行 insert,update,delete->commit/rollback
(1) 为了提高性能(2) 为了保持业务流程的完整性(3) 使用分布式事务
1 - 原子性( atomicity )事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全 部不执行。2 、一致性( consistency )事务在完成时,必须是所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。3 、隔离性( isolation )一个事务的执行不能被其他事务所影响。企业级的数据库每一秒钟都可能应付成千上万的并发访问,因 而带来了并发控制的问题。4 、持久性( durability )一个事务一旦提交,事务的操作便永久性的保存在 DB 中。即使此时再执行回滚操作也不能撤消所做的 更改
事务的传播机制事务的第一个方面是传播行为( propagation /,pr ɒ p ə ' ɡ e ɪʃə n/ behavior )。当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。规定了事务方法和事务方法发生嵌套调用时事务如何进行传播例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。Spring 定义了七种传播行为:
13.5 事务的隔离级别 MySQL 数据库共定义了四种隔离级别:1. Serializable( 串行化 ) :可避免脏读、不可重复读 , 幻读情况的发生。2. Repeatable read( 可重复读 ) :可避免脏读、不可重复读情况的发生。3. Read committed( 读已提交 ) :可避免脏读情况发生。4. Read uncommitted( 读未提交 ) :最低级别,以上情况均无法保证。Isolation.DEFAULT: 为数据源的默认隔离级别![]()
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.13</version></dependency>
<!-- 平台事务管理器 --><bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!-- 通知 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!-- 传播行为:propagation 不是必须的,默认值是REQUIRED --><!-- REQUIRED:如果有事务,则在事务中执行;如果没有事务,则开启一个新的事务 --><tx:method name="save*" propagation="REQUIRED" /><!-- SUPPORTS:如果有事务,则在事务中执行;如果没有事务,则不会开启事务 --><tx:method name="find*" propagation="SUPPORTS" read-only="true" /></tx:attributes></tx:advice><aop:config><aop:pointcut id="txPointCut" expression="execution(* com.service.*.* (..))" /><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/></aop:config>
使用 @Transactional 注解 - 添加 tx 命名空间
@Transactional // 对业务类进行事务增强的标注@Service("accountService")public class AccountServiceImpl implements AccountService {}
@Transactional("事务管理器的名字") //此处添加指定事务管理器的名字
@Service("accountService")public class AccountServiceImpl implements AccountService {}
<!-- 声明一个事务管理器 --><bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/><qualifier value=" 定义事务管理器的名字 , 可以被注解查找 " /></bean>
7 Spring-jdbc
<dependency>
<groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.0.8.RELEASE</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.46</version></dependency> 2. 测试<dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.0.8.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.8.RELEASE</version></dependency><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</version></dependency>
注意 : 可以自己在 RoleDaoImpl 中添加 JdbcTemplate 变量 , 如果不自动装载记得添加变量的 set 方法 ,标准的操作 , 我们可以让 RoleDaoImpl 继承 JdbcDaoSupport
public class RoleDaoImpl extends JdbcDaoSupport implements RoleDao {
public void save(Role role) {String sql = "INSERT INTO role (rname,alias) value (?,?) ;";getJdbcTemplate().update(sql,role.getRname(),role.getAlias());}}----------------------------------------------------配置文件 : 需要创建数据源和给 RoleDaoImpl 中的 jdbcTemplate 赋值<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"p:jdbcUrl="jdbc:mysql://localhost:3306/xzk"p:driverClass="com.mysql.jdbc.Driver"p:user="root"p:password="111"/><!-- bean jdbcTemplate --><bean name="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/></bean><bean name="roleDao" class="com.xzk.spring.dao.impl.RoleDaoImpl"><prope rty name="jdbcTemplate" ref="jdbcTemplate"/></bean>
7.3 创建db.properties属性文件
<context:property-placeholder location="db.properties" system-properties-mode="FALLBACK" > </context:property-placeholder>
p:jdbcUrl="${jdbc.jdbcUrl}"p:driverClass="${jdbc.driverClass}"
7.4 JdbcTemplate常用方法:
JdbcTemplate.update(sql,ArgsObj....); // 多个参数值时,可以使用对象数组jdbcTemplate.queryForObject(String var1, RowMapper var2, Object... var3);//查单个jdbcTemplate.query(String var1, RowMapper var2, Object... var3); // 查询所有getJdbcTemplate().query(sql,new BeanPropertyRowMapper< 类名 >( 类名 .class));// 查询 ( 单行 + 多行 )
实例:查询行数
String sql="select count(*) from users";
Integer integer = getJdbcTemplate().queryForObject(sql, Integer.class);查询多列Map<String, Object> map = jdbcTemplate.queryForMap(" select count(*),max(roleid),min(roleid) from role");Set<Map.Entry<String, Object>> entrySet = map.entrySet();Iterator<Map.Entry<String, Object>> iterator = entrySet.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}查询单列值String sql="select username from users";List<String> list = getJdbcTemplate().queryForList(sql, String.class);
By CaesarChang 张旭 合作: [email protected]
~关注我 带你看更多精品技术和面试必备
号码 1153132260