Spring简介

  1. spring核心

    • AOP:面向切面编程,扩展功能不是修改源代码实现
    • IOC:控制反转,将对象的创建交给spring
    • DI:依赖注入,前提必须有IOC的环境,Spring管理这个类的时候将类的依赖的属性注入(设置)进来。
  2. 一站式框架

    • web层:springMVC
    • service层:spring的IOC
    • dao层:spring的jdbcTemplate
  3. 优点:

    • 方便解耦、简化开发,Spring 就是一个大工厂,可以将对象创建和依赖关系的维护交给 Spring 管理
    • AOP 编程的支持,Spring 提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
    • 声明式事务的支持,只需要通过配置就可以完成对事务的管理,而无需手动编程
    • 方便程序的测试,Spring 对 Junit4 支持,可以通过注解方便的测试 Spring 程序
    • 方便集成各种优秀框架,Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz 等)的直接支持
    • 降低 JavaEEAPI 的使用难度,Spring 对 JavaEE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等),都提供了封装,使这些 API 应用难度大大降低

IOC(xml)

使用技术:xml配置文件、dom4j解决xml、工厂设计模式、反射

  1. 导入jar包(略)、创建类(略)
  2. 配置文件:引约束、对象创建

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 引入schema约束 -->
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xsi:schemaLocation="http://www.springframework.org/schema/beans                 
    http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!-- 配置对象创建 -->
        <bean id="user" class="com.vo.User" scope="prototype" ></bean>
    </beans>
  3. 写代码测试对象创建

    //1 加载spring配置文件,根据创建对象
    ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
    //2 得到配置创建的对象
    User user=(User) context.getBean("user");
    System.out.println(user);
    user.add();

bean管理

  1. bean标签常用属性:

    • id属性:起名称,id属性值名称任意命名,不能包含特殊符号
    • class属性:创建对象所在类的全路径
    • name属性:功能和id属性一样的,但是在name属性值里面可以包含特殊符号
    • scope属性

      • singleton:默认值,单例
      • prototype:多例
      • request:创建对象把对象放到request域里面
      • session:创建对象把对象放到session域里面
      • globalSession:创建对象把对象放到globalSession里面
  2. bean的三种实例化方式:

    1. 使用类的无参数构造创建

      <!-- ioc入门 -->
      <bean id="user" class="cn.itcast.ioc.User" scope="prototype"></bean>
    2. 使用静态工厂创建,创建静态的方法,返回类对象

       public class Bean2Factory { 
        //静态的方法,返回Bean2对象
        public static Bean2 getBean2() {
          return new Bean2();
        }
      } 

      配置文件

       <!-- 使用静态工厂创建对象 -->
       <bean id="bean2" class="cn.bean.Bean2Factory" factory-method="getBean2"></bean>
    3. 使用实例工厂创建,创建不是静态的方法,返回类对象

      public class Bean3Factory { 
        //普通的方法,返回Bean3对象
        public Bean3 getBean3() {
          return new Bean3();
        }
      } 

      配置文件

      <!-- 使用实例工厂创建对象 -->
      <!-- 创建工厂对象 -->
      <bean id="bean3Factory" class="cn.bean.Bean3Factory"></bean>
      <bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean>

属性注入

创建对象时候,设置对象属性的值

  1. 使用set方法注入

    <!-- 使用set方法注入属性 -->
    <bean id="book" class="cn.property.Book">
        <!--name属性值:类里面定义的属性名称
            value属性:设置具体的值-->
        <property name="bookname" value="易筋经"></property>
    </bean>
  2. 使用有参数构造注入

    <!-- 使用有参数构造注入属性 -->
    <bean id="demo" class="cn.property.PropertyDemo1">
        <!-- 使用有参构造注入 -->
        <constructor-arg name="username" value="小王"></constructor-arg>
    </bean> 

    代码

    private String username;
    public PropertyDemo1(String username) {
      this.username = username;
    }
  3. 使用接口注入,spring不支持

对象类型属性注入

<!-- 注入对象类型属性 -->
<!-- 1 配置service和dao对象 -->
<bean id="userDao" class="cn.ioc.UserDao"></bean>
<bean id="userService" class="cn.ioc.UserService">
    <!-- 注入dao对象-->
    <property name="userDao" ref="userDao"></property>
</bean>

复杂数据注入

<!-- 注入复杂类型属性值 -->
  <bean id="person" class="cn.property.Person">
    <!-- 数组 -->
    <property name="arrs">
       <list>
         <value>小王</value>
         <value>小马</value>
         <value>小宋</value>
       </list>
    </property>
    
    <!-- list -->
    <property name="list">
       <list>
         <value>小奥</value>
         <value>小金</value>
         <value>小普</value>
       </list>      
    </property>

    <!-- map -->
    <property name="map">
       <map>
         <entry key="aa" value="lucy"></entry>
         <entry key="bb" value="mary"></entry>
         <entry key="cc" value="tom"></entry>
       </map>
    </property>

    <!-- properties -->
    <property name="properties">
       <props>
         <prop key="driverclass">com.mysql.jdbc.Driver</prop>
         <prop key="username">root</prop>
       </props>
    </property>
  </bean>

IOC(注解)

注解写法 @注解名称(属性名称=属性值)
类、方法、属性
1 、导入jar包、创建类(略)

3、 配置文件:约束、开启注解扫描

<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" 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">
  <!-- 开启注解扫描,到包里面扫描类、方法、属性上面是否有注解  -->
  <context:component-scan base-package="cn.entity"></context:component-scan>
  <!-- 扫描属性上面的注解 -->
  <!-- <context:annotation-config></context:annotation-config> -->
</beans>
@Service(value="user")   // <bean id="user" class=""/>
public class User { 

测试类

ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
UserService userService = (UserService) context.getBean("userService");
userService.add();

bean管理

  • 四个注解

    1. @Component
    2. @Controller :web层
    3. @Service :业务层
    4. @Repository :持久层

目前这四个注解功能是一样的,都创建对象

  • 创建对象单实例还是多实例

    @Service(value="user")   // <bean id="user" class=""/>
    @Scope(value="prototype")

注入属性

Autowired、 Resource

  1. 创建dao和service对象

    @Component(value="userDao")
    public class UserDao {
        
    @Service(value="userService")
    public class UserService {
  2. 在service类里面定义dao类型属性

    @Autowired默认按类型装配(这个注解是属业spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用

    //得到dao对象
    //1 定义dao类型属性,在dao属性上面使用注解 完成对象注入
    @Autowired()@Qualifier("baseDao")
    private UserDao userDao; 
  3. 在service类里面定义dao类型属性

    // 使用注解方式时候不需要set方法。name=注解创建dao对象 value值
    @Resource(name="userDao")
    private UserDao userDao;

AOP

AOP是面向切面(方面)编程,扩展功能的同时不修改源代码。AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码

AOP底层使用动态代理实现

  1. 有接口情况,使用JDK动态代理创建接口实现类代理对象
  2. 没有接口情况,使用cglib动态代理创建类的子类代理对象

基本术语

  • Joinpoint(连接点):具体要增强的方法
  • Pointcut(切入点):连接点的集合 .
  • Advice(通知/增强):拦截到Joinpoint之后所要做的事情,切入切点的时机
    分为:前置通知、后置通知、异常通知、最终通知、环绕通知(切面要完成的功能)
  • Aspect(切面): 切点、连接点、通知所在的类为切面
  • Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.
  • Target(目标对象):代理的目标对象(要增强的类)
  • Weaving(织入):是把增强应用到目标的过程. 把advice 应用到 target的过程
  • Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类

操作准备

  1. 导包:基本的jar包、aop相关的jar包
  2. 配置文件,导入aop的约束

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

xml方式

在spring里面进行aop操作,使用aspectj实现。aspectj不是spring一部分,和spring一起使用进行aop操作;Spring2.0以后新增了对AspectJ支持

  1. 使用表达式配置切入点,常用的表达式

    execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)

    1. execution(* cn.aop.Book.add(..))
    2. execution( cn.aop.Book.(..))*
    3. execution( .(..))
    4. 匹配所有save开头的方法 execution( save(..))
  2. Aspectj的aop操作
      <!-- 1  配置对象 -->
      <bean id="book" class="cn.aop.Book"></bean><!--连接点-->
      <bean id="myBook" class="cn.aop.MyBook"></bean><!--切面-->

      <!-- 2 配置aop操作 -->
      <aop:config>
        <!-- 2.1 配置切入点 -->
        <aop:pointcut expression="execution(* cn.aop.Book.*(..))" id="pointcut1"/>    
        <!-- 2.2 配置切面 把增强用到方法上面 -->
        <aop:aspect ref="myBook">
           <!-- 配置增强类型 method: 增强类里面使用哪个方法作为前置-->
           <aop:before method="before1" pointcut-ref="pointcut1"/>       
           <aop:after-returning method="after1" pointcut-ref="pointcut1"/>       
           <aop:around method="around1" pointcut-ref="pointcut1"/>
        </aop:aspect>
      </aop:config>
  1. 切面(MyBook)代码:
        public void before1() {
            System.out.println("前置增强......");
        }

        public void after1() {
            System.out.println("后置增强......");
        }

        //环绕通知
        public void around1(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            //方法之前
            System.out.println("方法之前.....");

            //执行被增强的方法
            proceedingJoinPoint.proceed();

            //方法之后
            System.out.println("方法之后.....");
        }

注解方式

  1. 创建对象

    <!-- 1  配置对象 -->
    <bean id="book" class="cn.aop.Book"></bean>
    <bean id="myBook" class="cn.aop.MyBook"></bean>
  2. 在spring核心配置文件中,开启aop操作

    <!-- 开启aop操作 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  3. 在增强类上面使用注解完成aop操作

    @Aspect
    public class MyBook { 
      //在方法上面使用注解完成增强配置
      @Before(value="execution(* cn.aop.Book.*(..))")
      public void before1() {
        System.out.println("before..............");
      }
    }

jdbcTemplate操作

配置连接池

  1. 配置c3p0连接池

    导入jar包,创建spring配置文件,配置连接池

      <!-- 配置c3p0连接池 -->
      <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 注入属性值 -->
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql:///spring"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
      </bean>
      <!-- 创建service和dao对象,在service注入dao对象 -->
      <!-- 创建jdbcTemplate对象 -->
      <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!-- 把dataSource传递到模板对象里面 -->
        <property name="dataSource" ref="dataSource"></property>
      </bean>
      
      <bean id="userDao" class="cn.c3p0.UserDao">
        <!-- 注入jdbcTemplate对象 -->
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
      </bean>
     
      <bean id="userService" class="cn.c3p0.UserService">
        <!-- 注入dao对象 -->
        <property name="userDao" ref="userDao"></property>
      </bean>
    

CRUD操作

  1. 增加、修改、删除,调用模板方法

      public void delete() {
        //设置数据库信息
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///spring3");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        
        //创建jdbcTemplate对象,设置数据源
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        
        //调用update方法
        //增
        String sql = "insert into user values(?,?)";
        int rows = jdbcTemplate.update(sql, "lucy");
     
        //改
        String sql = "update user set password=? where usename=?";
        int rows = jdbcTemplate.update(sql,"1234", "lucy");
     
        //删
        String sql = "delete from user where username=?";
        int rows = jdbcTemplate.update(sql, "lucy");
     
        System.out.println(rows);
      }
    
  2. 查询

    • 查询某个值时候,调用queryForObject方法。自己写实现类封装数据

      在dbutils时候,有接口 ResultSetHandler,dbutils提供了针对不同的结果实现类

      jdbcTemplate实现查询,有接口 RowMapper,jdbcTemplate针对这个接口没有提供实现类,得到不同的类型数据需要自己进行数据封装

        public void testCount() {
          //设置数据库信息
          DriverManagerDataSource dataSource = new DriverManagerDataSource();
          dataSource.setDriverClassName("com.mysql.jdbc.Driver");
          dataSource.setUrl("jdbc:mysql:///spring_day03");
          dataSource.setUsername("root");
          dataSource.setPassword("root");
          
          //创建jdbcTemplate对象
          JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
          
          //调用方法得到记录数
          String sql = "select count(*) from user";
          //调用jdbcTemplate的方法
          int count = jdbcTemplate.queryForObject(sql, Integer.class);
          System.out.println(count);
        }
      
    • 查询对象,调用queryForObject方法

        //3 查询返回对象
        @Test
        public void testObject() {
          //设置数据库信息
          DriverManagerDataSource dataSource = new DriverManagerDataSource();
          dataSource.setDriverClassName("com.mysql.jdbc.Driver");
          dataSource.setUrl("jdbc:mysql:///spring_day03");
          dataSource.setUsername("root");
          dataSource.setPassword("root");
          
          //创建jdbcTemplate对象
          JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
          
          //写sql语句,根据username查询
          String sql = "select * from user where username=?";
          //调用jdbcTemplate的方法实现
          //第二个参数是接口 RowMapper,需要自己写类实现接口,自己做数据封装
          User user = jdbcTemplate.queryForObject(sql, new MyRowMapper(), "mary");
          System.out.println(user);
        }
       
      class MyRowMapper implements RowMapper<User> {
       
        @Override
        public User mapRow(ResultSet rs, int num) throws SQLException {
          // 1 从结果集里面把数据得到
          String username = rs.getString("username");
          String password = rs.getString("password");
          
          // 2 把得到数据封装到对象里面
          User user = new User();
          user.setUsername(username);
          user.setPassword(password);
          
          return user;
        }
        
      }
      
    • 查询list集合,调用query方法

       
        //4 查询返回对象
        @Test
        public void testList() {
          
      //  ComboPooledDataSource dataSource = new ComboPooledDataSource();
      //  dataSource.setDriverClass("com.mysql.jdbc.Driver");
      //  dataSource.setJdbcUrl("jdbc:mysql:///spring_day03");
      //  dataSource.setUser("root");
      //  dataSource.setPassword("root");
          
          //设置数据库信息
          DriverManagerDataSource dataSource = new DriverManagerDataSource();
          dataSource.setDriverClassName("com.mysql.jdbc.Driver");
          dataSource.setUrl("jdbc:mysql:///spring_day03");
          dataSource.setUsername("root");
          dataSource.setPassword("root");
          
          //创建jdbcTemplate对象
          JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
          
          //写sql语句
          String sql = "select * from user";
          //调用jdbcTemplate的方法实现
          List<User> list = jdbcTemplate.query(sql,new MyRowMapper());
          
          System.out.println(list);
          
        }
      }
       
       
      class MyRowMapper implements RowMapper<User> {
       
        @Override
        public User mapRow(ResultSet rs, int num) throws SQLException {
          // 1 从结果集里面把数据得到
          String username = rs.getString("username");
          String password = rs.getString("password");
          
          // 2 把得到数据封装到对象里面
          User user = new User();
          user.setUsername(username);
          user.setPassword(password);
          
          return user;
        }
        
      }
      

spring事务管理

  1. 基于xml配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <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: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.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
      http://www.springframework.org/schema/tx
      http://www.springframework.org/schema/tx/spring-tx.xsd">
      
      <!-- 配置c3p0连接池 -->
      <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 注入属性值 -->
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql:///spring3"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
      </bean>
      
      <!-- 第一步 配置事务管理器 -->
      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 注入dataSource -->
        <property name="dataSource" ref="dataSource"></property>
      </bean>
      
      <!-- 第二步 配置事务增强 -->
      <tx:advice id="txadvice" transaction-manager="transactionManager">
        <!-- 做事务操作 -->
        <tx:attributes>
           <!-- 设置进行事务操作的方法匹配规则  -->
           <tx:method name="account*" propagation="REQUIRED"/>
           <!-- <tx:method name="insert*" /> -->
        </tx:attributes>
      </tx:advice>
      
      <!-- 第三步 配置切面 -->
      <aop:config>
        <!-- 切入点 -->
        <aop:pointcut expression="execution(* cn.service.OrdersService.*(..))" id="pointcut1"/>
        <!-- 切面 -->
        <aop:advisor advice-ref="txadvice" pointcut-ref="pointcut1"/>
      </aop:config>
      
      <bean id="ordersService" class="cn.service.OrdersService">
        <property name="ordersDao" ref="ordersDao"></property>
      </bean>
      <bean id="ordersDao" class="cn.dao.OrdersDao">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
      </bean>
      <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
      </bean>
    </beans>
  2. 基于注解方式

    <!-- 第一步配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- 第二步 开启事务注解 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    第三步 在要使用事务的方法所在类上面添加注解

    @Transactional
    public class OrdersService {

Junit测试配置

  1. maven 配置

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>4.3.12</version>
        <scope>test</scope>
    </dependency>
  2. 创建BaseJunit4Test基类

    用来加载配置文件、设置web环境。所有测试类,都继承该类即可

    @RunWith(SpringJUnit4ClassRunner.class) //使用junit4进行测试
    @ContextConfiguration(locations={"classpath:spring.xml","classpath:spring-mvc.xml","classpath:spring-hibernate.xml","classpath:spring-ehcache.xml"}) //加载配置文件
    @WebAppConfiguration("src/main/webapp")
    //如果加入以下代码,所有继承该类的测试类都会遵循该配置,也可以不加,在测试类的方法上
    //这个非常关键,如果不加入这个注解配置,事务控制就会完全失效!
    //@Transactional
    //这里的事务关联到配置文件中的事务控制器(transactionManager = "transactionManager"),同时//指定自动回滚(defaultRollback = true)。这样做操作的数据才不会污染数据库!
    //@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
    public class BaseJunit4Test{
    }
  3. 测试类

    public class UserTest extends BaseJunit4Test{
        @Autowired //自动注入
        private UserManagerService userManagerService;
        
        @Test
        @Transactional //标明此方法需使用事务
        @Rollback(false) //标明使用完此方法后事务不回滚。true时为回滚,不会污染数据库!
        public void testUser(){
            System.out.println("测试Spring整合Junit4进行单元测试");
            AdeUser user = userManagerService.get("0");
            System.out.println(user);
            System.out.println("------------"+user.getLoginName());
        }
    }

messchx
58 声望5 粉丝

下一篇 »
SpringMVC整理