Java后台—Spring

1. Spring介绍

Spring的核心是控制反转(IoC)和面向切面(AoP)。
总共分为三层结构:

  • WEB层:Spring MVC
  • 业务层:Bean管理(IOC)
  • 持久层:Spring的JDBC模板,ORM模板用于整个其他的持久层框架
    Spring 的Bean属性注入:

1.1 Sping架构

这里写图片描述

  • 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。

  • Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
    Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring - - AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。

  • Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。

  • Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。

  • Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

  • Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

1.2 Spring配置

  1. 依赖包的注入
    Alt text
  2. 引入相关的配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    >
    //引入约束

 <!--将User对象交给Spring容器管理-->
    <!--Bean元素;使用该元素描述需要spring容器管理的对象-->
    <bean name="user" class="cn.raine.bean.User"></bean>
</beans>

1.3 Spring的工厂 (容器)

ApplicationContextBeanFactory(在内存资源少的时候使用已过时)
区别
BeanFactory :是在 getBean 的时候才会生成类的实例.
ApplicationContext :在加载 applicationContext.xml(容器启动)时候就会创建.
获取容器

 //创建容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        User u = (User) ac.getBean("user");
        System.out.print(u);

1.4 Spring相关配置属性

  • id属性:Bean 起个名字. 在约束中采用 ID 的约束:唯一. 必须以字母开始,可以使用字母、数字、连字符、 下划线、句话、冒号 id:不能出现特殊字符.
  • name属性:Bean 起个名字. 没有采用 ID 的约束. name:出现特殊字符.如果<bean>没有 id 的话 , name 可 以当做 id 使用.
  • scop属性
  • singleton : 默认值,单例的
  • prototype: 多例的
1.4.1 Bean的生命周期

通过配置<bean>标签上的init-method 作为 Bean 的初始化的时候执行的方法,配置 destroy-method作为 Bean 的销毁的时候执行的方法。 销毁方法想要执行,需要是单例创建的 Bean 而且在工厂关闭的时候,Bean 才会被销毁

1. 5 Spring的注入

  1. Spring的bean的属性注入
  • 构造方法的注入方式
<!-- 第一种:构造方法的方式 -->  
<bean id="car" class="cn.itcast.spring.demo4.Car"> 
  <constructor-arg name="name" value=" 保时捷 "/>   
  <constructor-arg name="price" value="1000000"/> 
 </bean> 
  • set方法的注入属性
<!-- 第二种:set 方法的方式 -->  
<bean id="car2" class="cn.itcast.spring.demo4.Car2"> 
  <property name="name" value=" 奇瑞 QQ"/>   
  <property name="price" value="40000"/>  
  </bean> 
  1. 对象类型的注入
 <!-- 注入对象类型的属性 -->  
 <bean id="person" class="cn.itcast.spring.demo4.Person"> 
  <property name="name" value=" 会希 "/>   
  <!-- ref 属性:引用另一个 bean 的 id 或 name -->   
  <property name="car2" ref="car2"/> 
   </bean> 
  1. 复杂类型的注入
 <!--复杂类型的注入-->
    <bean name="cb" class="cn.raine.injection.CollectionBean">
        <property name="arr">
            <list>
                <value>会希</value>
                <value>哈哈</value>
            </list>
        </property>
        <property name="list">
            <list>
                <value>javck</value>
                <value>jerry</value>
                <ref bean="user2"></ref>
            </list>
        </property>
    </bean>

构造函数注入的时候

//确定使用哪个构造函数
<constructor-arg name="name" index="0" type="java.lang.Interger"/>

listener是spring web 包

2. AOP

2.1 使用注解配置Spring

头部约束

<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"
       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.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd"

    >

xml中写入

     <!--指定扫描cn.raine.bean下的所有类的注解
    注意:扫描包时,会扫描指定包下所有的子包
    -->
    <context:component-scan base-package="cn.raine.bean"></context:component-scan>

代码注解

//将对象注入到容器
Component("user")
Service("user")   //Service层
Controller("user")	//web层
@(后台)Repository("user")	//dao层

//值类型的注入
@Value("tom")
public void setNmae(String name){
...
}

//引用类型的注入
@Autowired  //自定装配
private Car car;
@Resource(name="car"//手动注入,指定注入哪个名称的对象
private Car car;

Spring 的 Bean 管理的方式的比较
Alt text

2.2 Sping接入整合Junit测试

RunWith(SpringJUnit4ClassRunner.class)  //帮我们创建容器
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo {

    @Resource(name = "user")
    private User u;
    
    @Test
    public void fun1(){
}

2.3 Sping的AOP介绍

2.3.1 底层实现

代理机制

  • Spring的AOP的底层用到两种代理机制:
  • JDK的动态代理:针对实现了接口的产生代理
  • Cglib的到动态代理:针对没有实现接口的类产生代理,应用的是底层的字节码增强的技术,深层当前类的子类对象。
2.3.2 AOP的开发中的相关术语
  • Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只 支持方法类型的连接点.
  • Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义.
  • Advice(通知/增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知.通知分为前置通知,后置 通知,异常通知,最终通知,环绕通知(切面要完成的功能)
  • Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类 动态地添加一些方法或 Field.
  • Target(目标对象):代理的目标对象
  • Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程. spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装在期织入
  • Proxy(代理):一个类被 AOP 织入增强后,就产生一个结果代理类
  • Aspect(切面): 是切入点和通知(引介)的结合
2.3.2 AOP的开发

jar包介绍
Alt text
步骤

<!--准备工作:导入aop(约束)命名空间-->

    <!--1.配置目标对象-->
    <!--2.配置通知对象-->
    <!--3.配置将通知织入目标对象-->
    <!-- 配置切入点
        * cn.itcast.service..*ServiceImpl.*(..)
        这个service包下面的任意子包中以ServiceImpl结尾的任意类中的任意方法(任意参数)  可以返回任意类型数据
    -->
前置通知 :在目标方法执行之前执行. 
后置通知 :在目标方法执行之后执行 
环绕通知 :在目标方法执行前和执行后执行 
异常抛出通知:在目标方法执行出现 异常的时候 执行 
最终通知 :无论目标方法是否出现异常 最终通知都会 执行. 

目标类的创建:

//创建接口和类:
 public interface OrderDao {  
 public void save();  
 public void update();  
 public void delete(); 
 public void find(); 
 } 
 public class OrderDaoImpl implements OrderDao { 
 
 @Override  public void save() { 
  System.out.println("保存订单...");  
@Override  public void update() { 
  System.out.println("修改订单...");  } 
 
 @Override  public void delete() { 
  System.out.println("删除订单...");  } 
 
 @Override  public void find() { 
  System.out.println("查询订单...");  } 
 
} 
} 

目标类的配置

<!-- 目标类================ -->  
<bean id="orderDao" class="cn.itcast.spring.demo3.OrderDaoImpl">    </bean>

整合Jubit单元测试

引入 spring-test.jar 
 
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("classpath:applicationContext.xml") 
public class SpringDemo3 {  
	@Resource(name="orderDao")  
	private OrderDao orderDao;    
	@Test  
	public void demo1(){   
		orderDao.save();   
		orderDao.update();   
		orderDao.delete();   
		orderDao.find();  
} } 

编写切入面

public class MyAspectXml { 
 // 前置增强  
 public void before(){ 
  System.out.println("前置增强===========");  
  
  } }

配置完成增强

 <!-- 配置切面类 -->  
 <bean id="myAspectXml" class="cn.itcast.spring.demo3.MyAspectXml"></bean>   
 <!-- 进行 aop 的配置 -->  
 <aop:config> 
  <!-- 配置切入点表达式:哪些类的哪些方法需要进行增强 -->   
  <aop:pointcut expression="execution(* cn.itcast.spring.demo3.OrderDao.save(..))" id="pointcut1"/> 
  <!-- 配置切面 -->   
  <aop:aspect ref="myAspectXml">    
  <aop:before method="before" pointcut-ref="pointcut1"/>   
  </aop:aspect>  
  </aop:config> 

切入点表达式:

execution(表达式) 
表达式: [方法访问修饰符] 方法返回值 包名.类名.方法名(方法的参数)
 public * cn.itcast.spring.dao.*.*(..)
* cn.itcast.spring.dao.*.*(..)
* cn.itcast.spring.dao.UserDao+.*(..)
* cn.itcast.spring.dao..*.*(..)

3. Spring整合JDBC

3.1 Spring连接JDBC

导入jar包

Alt text

编写Dao文件
public class UserDaoImpl extends JdbcDaoSupport implements UserDao {
//引入了JDBCDaoSupport根据连接池创建JDBC模板,直接从父类方法中获得就可以了

    @Override
    public void save(User u) {
        String sql = "insert into s_user values(null, ?)";
        getJdbcTemplate().update(sql, u.getName());
    }

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

    @Override
    public void update(User u) {
        String sql = "update s_user set name = ? where id = ?";
        getJdbcTemplate().update(sql, u.getName(), u.getId());
    }

//查询单个对象
    @Override
    public User getById(Integer id) {
        String sql = "select * from s_user where id = ?";

        return getJdbcTemplate().queryForObject(sql, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet rs, int i) throws SQLException {
                User u = new User();
                u.setId(rs.getInt("id"));
                u.setName(rs.getString("name"));
                return u;
            }
        });
    }

//查询值类型
    @Override
    public int getTotalCount() {
        String sql = "select count(*) from t_user  ";
        Integer count = super.getJdbcTemplate().queryForObject(sql, Integer.class);
        return count;
    }

//查询list集合类型
    @Override
    public List<User> getAll() {
        String sql = "select * from s_user";
        List<User> list = getJdbcTemplate().query(sql, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet rs, int i) throws SQLException {
                User u = new User();
                u.setId(rs.getInt("id"));
                u.setName(rs.getString("name"));
                return u;
            }
        });
        return list;
    }

}
Spring配置
<!--指定spring读取db.properties配置-->
    <context:property-placeholder location="classpath:db.properties"/>
  <!--指定spring读取db.properties配置-->
    <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
        <property name="driverClass" value="${jdbc.driverClass}"></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>

    <!-- 3.将UserDao放入spring容器 -->
    <bean name="userDao" class="cn.raine.jsbctemplate.UserDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
     </bean>

3.2 事务

3.2.1 事务特性
  • 原子性 :强调事务的不可分割.
  • 一致性 :事务的执行的前后数据的完整性保持一致.
  • 隔离性 :一个事务执行的过程中,不应该受到其他事务的干扰
  • 持久性 :事务一旦结束,数据就持久到数据库
3.2.2设置事务隔离级别
  • 未提交读 :脏读,不可重复读,虚读都有可能发生
  • 已提交读 :避免脏读。但是不可重复读和虚读有可能发生
  • 可重复读 :避免脏读和不可重复读.但是虚读有可能发生.
  • 串行化的 :避免以上所有读问题.
    ####3.2.3 真正管理事务的对象
***** 真正管理事务的对象 
org.springframework.jdbc.datasource.DataSourceTransactionManager 使用 Spring JDBC 或 iBatis 进行持久化数据时使用 
org.springframework.orm.hibernate3.HibernateTransactionManager  使用 Hibernate 版本进行持久化数据时使用 
3.2.4 事务的传播行为

PROPAGION_XXX :事务的传播行为

  • 保证同一个事务中
    PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认) PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务
    PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常

  • 保证没有在同一个事务中
    PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务
    PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务
    PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常
    PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行

3.2.5 Spring管理事务方式
3.2.5.1 xml配置

xml配置

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

    <!--事务模板对象-->
    <bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager"></property>
    </bean>

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

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

 <bean name="accountDao" class="cn.raine.dao.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <bean name="accountService" class="cn.raine.service.AccountServiceImpl">
        <property name="ad" ref="accountDao"></property>
        <property name="tt" ref="transactionTemplate"></property>
    </bean>

在Service中调用模板

    public void transfer(Integer from, Integer to, Double money) {
        tt.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                //减钱
                ad.decreaseMoney(from, money);

                //加钱
                ad.increaseMoney(to, money);
            }
        });
3.2.5.2 注解配置

开启注解管理事务

  <!--开启使用注解管理aop事务-->
    <tx:annotation-driven/>

使用注解

   @Override
    @Transactional(isolation = ![这里写图片描述](http://img.blog.csdn.net/20171210101028916?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTGVicm9uX3hpYQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW, readOnly = false)
    public void transfer(Integer from, Integer to, Double money) {
        //减钱
        ad.decreaseMoney(from, money);
      //  int i = 1/0;
        //加钱
        ad.increaseMoney(to, money);
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值