SSM框架之Spring

认识spring

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

轻量级:从大小与开销两方面 都是轻量级的。spring框架的jar 很小,运行spring框架的开销很小

非入侵:在代码开发中,一般不会入侵spring代码

控制反转(IOC):把对象的创建权利交给了容器。

面向切面编程(AOP):

 

为什么使用spring框架:

  1. 降低组件之间的耦合度,实现各层之间的松耦合
  2. 容器还提供了多种设计模式,比如单例模式
  3. 容器提供了AOP技术,可以非常容易的实现 权限、事物管理
  4. 对其他主流框架的兼容
  5. 等等

spring入门程序

spring的核心

核心配置文件或者是核心类 作用  
*.xml (applicationContext.xml默认) 用于配置所有的类 ,这些类称为springBean  
BeanFactory(接口) 容器的工厂类,用于创建或者是获取springBean,也就是spring配置文件中的类 懒加载
ApplicationContext(接口) 它是BeanFactory的子类,叫做应用上下文对象,功能比BeanFactory更加强大 非懒加载

 

 

 

 

 

 

public class Person {
	private String name;	
	public void eat() {
		System.err.println(name + ":eatting......");
	}
	<!-- 配置第一个springbean 
	相当于Person person  = new Person();
	class:配置的类  id:唯一标识
	-->
	<bean class="com.cbb.bean.Person" id="person"></bean>
	//加载spring的核心配置文件,初始化spring容器,创建springbean的实例
	ApplicationContext ctx =
			new ClassPathXmlApplicationContext("applicationContext.xml");
	//获取容器的实例
	Person p = (Person) ctx.getBean("person");
	//调用方法测试
	p.setName("rose");
	p.eat();

控制反转:IOC

inversion of control  定义:把对象的创建、初始化、销毁等工作 交给spring容器来做,由spring容器来管理对象的生命周期。

IOC不是一种技术,知识一种开发思想,一种重要的面向对象编程的法则。可以设计出松耦合、更加优良的系统程序

IOC包括两部分:依赖注入(DI) 和依赖查找

spring的注入:就是在实例化这个类的时候,由外部的容器来设置这个对象的值

public class User {
	
	private int id;
	
	private String name;
	
	private List<String> scores;
	
	private Map<String, Object> info;
    
    setter方法

    
	<!-- 属性的注入 -->
	<bean id="user" class="com.cbb.bean.User">
		<!-- 注入必须保证注入的属性要有setter方法  
		<property> 进行配置的  name指的是哪个属性  value是具体设置的值
		-->
		<property name="id" value="2"></property>
		
		<property name="name" value="jack"></property>
		
		<property name="scores" >
			<list>
				<value>100</value>
				<value>80</value>
			</list>
		</property>
		
		<property name="info">
			<map>
				<entry key="age" value="23"></entry>
				<entry key="school" value="哈佛"></entry>
			</map>
		</property>
	</bean>

注入其他类

		<!-- 通过ref 指向其他bean的引用 -->
		<property name="car" ref="myCar">
		</property>
	</bean>
	
	<bean id="myCar" class="com.cbb.bean.Car">
		<property name="carName" value="BMW"></property>
	</bean>

Bean的作用域

通过bean的scope进行配置

	<bean id="myCar" class="com.cbb.bean.Car" scope="singleton">
		<property name="carName" value="BMW"></property>
	</bean>
  1. singleton:单例模式(缺省默认),spring容器中只存在一个实例。
  2. prototype:原型模式,每次通过spring容器获取bean时,容器会创建一个新的实例进行返回。
  3. request:在同一次请求中,获取的是同一个实例,不同的请求获取的是不同的实例
  4. session:再同一次会话中,获取的是同一个实例....

bean的装配

1.配置文件xml的装配方式

注意两点:

  1. 属性注入需要有 对应的setter方法
  2. 注入的其他类 bean要有无参构造方法
<bean id="userController" class="com.cbb.controller.UserController">
    <property name="userService" ref="us"></property>
</bean>

<bean id="us" class="com.cbb.service.impl.UserServiceImpl">
    <property name="userDao" ref="ud"></property>
</bean>

<bean id="ud" class="com.cbb.dao.impl.UserDaoImpl"></bean>
public class UserServiceImpl implements UserService{
    
    public UserServiceImpl(String str) {}
    public UserServiceImpl() {
        super();
    }
    private UserDao userDao ;

    @Override
    public void login() {
        System.err.println("service.....login.......");
        userDao.login();
    }

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

2.注解的装配方式

导入jar 多了一个spring-aop-4.1.3.RELEASE.jar

<?xml version="1.0" encoding="UTF-8"?>
<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">
	
	<!-- 扫描包下 的注解的组件,把他们自动的注册到springbean中 -->
	<context:component-scan base-package="com.cbb"></context:component-scan>
	

</beans>
//以下四个注解共同的作用:注解到springbean中的注解,要注解到类的头上 ;默认bean的名字是  首字母小写的类名,比如本例就是"userDaoImpl"
@Component  //是组件的通用形式
@Controller  //控制层,表示web层组件
@Service    //业务层
@Repository  //持久层    ("ud") 这是自定义bean的名字

@Autowired //1.按照类型进行装配,会到springbean中根据类型去查询并且进行注入  2.无需setter方法  
//问题:如果有两个类型都匹配,就报错需要用 @Qualifier //指定bean的名字
//@Resource //会根据属性的名字去查找对应的bean,如果查找不到,则再根据类型进行匹配

spring+mybatis整合

整合思想:mybatis是一个持久层框架,用来操作数据库的

spring是一个容器框架,用来管理对象的 。

  • 使用spring容器 来管理  单例模式的会话工厂SqlSessionFactory
  • 使用spring容器来管理mapper的动态代理对象

spring核心配置文件

	<!-- 1.数据源  2.扫描包 注册一些bean 3.会话工厂SqlSessionFactory 4.mapper的代理对象bean-->
	
	<!-- 加载外部的资源文件 -->
	<context:property-placeholder location="db.properties"/>
	<!-- 配置数据库连接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${jdbc.driver}"></property>
		<property name="jdbcUrl" value="${jdbc.url}"></property>
		<property name="user" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property>
	</bean>
	
	<!-- 扫描注解  自动注册bean -->
	<context:component-scan base-package="com.cbb"></context:component-scan>
	
	<!-- 配置会话工厂,让spring容器来管理会话工厂,单例模式。mybatis-spring.jar下的类 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 注入属性:mybatis的配置文件、数据源 -->
		<property name="dataSource" ref="dataSource"></property>
		<!-- mybatis的配置文件 -->
		<!-- <property name="configLocation" value="mybatis.xml"></property> -->
		<!-- 起别名 -->
		<property name="typeAliasesPackage" value="com.cbb.pojo"></property>
	</bean>
	
	<!-- mapper的代理bean,使用包扫描加载的方式,批量的生成mapper的代理bean,bean的名字 就是接口的名字,首字母小写 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<!-- 指定mapper接口的包路径 -->
		<property name="basePackage" value="com.cbb.mapper"></property>
	</bean>

AOP面向切面编程

AOP:面向切面编程 希望达到核心业务与 系统服务之间相对独立,而又想让核心业务带着系统层面的功能,实现这 种效果的技术我们就称之为AOP。 AOP采用的是横向抽取机制,将分散在各个方法中的重复代码抽取出来,然后在 程序的编译期或者是运行期在将这些代码运行到需要执行的地方。

AOP的本质就是对方法进行增强。 通过代理的方式进行的

aop代理的实现方式:

JDK动态代理:基于接口的

CGLIB代理: 通过字节码进行的

SSM框架之Spring

SSM框架之Spring

SSM框架之Spring

AOP的核心:

通知 Advice:在哪个时间点上去做增强。方法执行前?执行后?返回后?异常后?

切点 PointCut:对哪些类、哪些方法进行增强。

AOP = 通知+切点。

Advice通知的类型:

前通知: 方法执行前

后通知: 方法执行后 返回后通知: 成功返回后

环绕通知: 方法执行的前后分别做一些增强

异常通知: 抛出异常后

PointCut切点:

基于正则表达式的切点 JDKR**PointCut

基于AOP的切点表达式AspectJ AspectJEx*PointCut 重点

AspectJ开发 :配置文件

	<!-- 待被功能增强的 类 -->
	<bean id="pserson" class="com.cbb.bean.Person"></bean>
	
	<!-- 配置一个切面 -->
	<bean id="myAdvice" class="com.cbb.advice.MyAdvice"></bean>
	
	<!-- aop配置 -->
	<aop:config>
		<!-- 配置切面  要通过ref:指向做增强的bean切面-->
		<aop:aspect ref="myAdvice">
			<!-- 配置切点  可以放到切面里面,代表只有本切面可以使用这个切点; 也可以放到切面外部, 代表全局的,所有的切面都可以使用这个切点
				 expression: 写切点表达式-->
			<aop:pointcut expression="execution(* com.cbb.bean.*.*(..))" id="myCut"/>
			<!-- 配置前通知   method:对应切面的哪个方法   pointcut-ref:配置切面的引用-->
			<aop:before method="doBefore" pointcut-ref="myCut"/>
		</aop:aspect>
	</aop:config>

切点表达式

写法: execution(返回类型 包路径.类.方法(参数类型) )

SSM框架之Spring

功能:

1. 可以控制返回值

2. 可以控制参数

3. 可以控制类的 深度

4. 面向接口的。 接口方法被切,则此接口的实现类方法也会被切。

符号 功能
* 在返回值上,代表的是任意类型。 在路径上,代表任意类或者是方法
.. 任意多个。0~N个

 

 

 

 

execution(* com.cbb.*.*(..)) 对com.cbb包下的所有类切,但是对子包下的类无效

execution(* com.cbb..*.*(..)) 对com.cbb包下 和 子包下的所有类切

通知的配置

	<!-- aop配置 -->
	<aop:config>
		<!-- 配置切面  要通过ref:指向做增强的bean切面-->
		<aop:aspect ref="myAdvice">
			<!-- 配置切点  可以放到切面里面,代表只有本切面可以使用这个切点; 也可以放到切面外部, 代表全局的,所有的切面都可以使用这个切点
				 expression: 写切点表达式-->
			<aop:pointcut expression="execution(* com.cbb..*.*(..))" id="myCut"/>
			<!-- 配置前通知   method:对应切面的哪个方法   pointcut-ref:配置切面的引用-->
			<aop:before method="doBefore" pointcut-ref="myCut"/>
			<!-- 后通知 : 可以称为最终通知,无论如何都会执行的-->
			<aop:after method="doAfter" pointcut-ref="myCut"/>
			<!-- 返回后通知 : 只有正常返回才会执行 -->
			<aop:after-returning method="afterR" pointcut-ref="myCut"/>
			<!-- 异常通知 : 只有异常抛出才会执行..-->
			<aop:after-throwing method="doThrow" pointcut-ref="myCut"/>
			<!-- 环绕通知: = 前通知+返回后通知   在待增强的方法执行的前后执行-->
			<aop:around method="doAround" pointcut-ref="myCut"/>
		</aop:aspect>
	</aop:config>
public class MyAdvice {

	public void doBefore(){
		System.err.println("前通知...");
	}
	
	public void doAfter(){
		System.err.println("后通知....");
	}
	
	public void afterR(){
		System.err.println("返回后通知....");
	}
	
	public void doThrow(){
		System.err.println("异常通知...");
	}
	
	/**
	 * joinPoint: 连接点
	 * @param joinPoint
	 * @throws Throwable 
	 */
	public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable{
		System.err.println("环绕通知开始....");
		Object obj = joinPoint.proceed();
		System.err.println("环绕通知结束....");
		return obj;
	}
}

spring事务管理

事务是逻辑上的一组操作,把它看成一个逻辑单元,要么一起成功,要么一起失败。

spring-tx.jar

spring-jdbc.jar

配置文件的方式

	<!-- spring事务管理的配置 -->
	<!-- 事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 注入数据源 -->
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 事务的通知 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<!-- name:配置的是需要进行事务管理的方法 *是通配符 
				propagation传播行为
						:REQUIRED :默认值(缺省的)当前的方法必须运行在事务中,如果当前没有事务则会开启一个新的事务。如果当前有事务,则使用当前的事务。
						SUPPORTS : 当前方法 如果有事务则使用当前的事务,如果没有事务则无需进行事务管理,比较适合于查询方法
			-->
			<tx:method name="*" propagation="REQUIRED"/>
			<tx:method name="select*" propagation="SUPPORTS"/>
		</tx:attributes>
	</tx:advice>
	
	<!-- 事务的aop配置 -->
	<aop:config>
		<aop:pointcut expression="execution(* com.cbb.service..*.*(..))" id="txCut"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txCut"/>
	</aop:config>

注解的配置

	<!-- spring事务管理的配置 -->
	<!-- 事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 注入数据源 -->
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 事务的注解驱动 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>
//@Transactional(noRollbackFor=java.lang.ArithmeticException.class)  不对java.lang.ArithmeticException.class异常回滚
@Transactional //事务管理的注解  可以放在需要事务管理的方法上,也可以放到类上,放到类上 代表类所有的方法都需要事务管理

注意:需要被spring进行事务管理,则应该不能自己处理异常,把异常外外抛。

 

相关文章: