【读过的书,留下的迹】Spring实战(第3版)

第1章:Spring之旅

  • 简单得说,spring通过面向POJO编程、依赖注入、AOP和模板技术来简化Java开发的复杂性

第2章:装配Bean

    
    
        org.springframework
        spring-context
        4.3.7.RELEASE
    
    
        javax.inject
        javax.inject
        1
    

(1)声明Bean


<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-3.0.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <bean id="duke" class="spring.test.bean.Juggler">
        
        <constructor-arg value="15" />
        
        <constructor-arg ref="sonnet29" />
    bean>

    
    <bean id="stage" class="spring.test.bean.Stage"
        factory-method="getInstance" />

    
    <bean id="duke" class="spring.test.bean.Ticket" 
        scope="prototype"/>

    
    <bean id="kenny" class="spring.test.bean.Instrumentalist">
        <property name="song" value="Jingle Bells" />
        <property name="instrument" ref="saxophone" />
                
    bean>

    
    <bean id="saxophone" class="spring.test.bean.Saxophone" >
        <property name="saxophone" value="#{SpEL}"
    bean>
beans>

第3章:最小化Spring XML配置

(1)自动装配Bean属性

  • byName:把与Bean得属性具有相同名字的其他Bean自动装配
  • byType:相同属性的
  • constructor:与构造器具有相同属性的
  • autodetect:首先尝试constructor,再尝试byName
<beans
    -- 省略一大堆 -->
    
    default-autowire="byType">
    <bean id="duke" class="spring.test.bean.Juggler"
        autowire="byType">
        
    bean>
    <bean id="duke2" class="spring.test.bean.Juggler"
        primary="false">
        
    bean>
    <bean id="duke2" class="spring.test.bean.Juggler"
        autowire-candidate="false">
        
    bean>
beans>

(2)使用注解装配

<beans/>  
    
    <context:annotation-config>
    <bean id="duke3" class="spring.test.bean.Juggler" >
        <qualifier value="test" />
        
    bean>
beans>
  • 使用@Autowired
    • @Qualifier(“id”)
    • @Qualifier(“value”)
    • 自定义Qualifier,新建一个类
  • 使用@Inject:跟Autowired用法基本一样,是Java依赖注入规范
    • 配套使用的是 @Named 加限定

(3)自动检测Bean

  • 转为Bean的注解
    • @Component:通用的构造型注解,标识伪Spring组件
    • @Controller:SpringMVC controller注解
    • @Repository:标识数据仓库
    • @Service:标识服务
<beans/>  
    
    <context:component-scan base-package="spring.test.bean">
    <context:include-filter type="assignable"
        expression="some.class" />
    <context:exclude-filter type="assignable"
        expression="some.class" />
    context:component-scan>
beans>
  • 过滤组建扫描
    • annotation:过滤注解的类
    • assignable:过滤派生于注解的类
    • 等等

(4)使用基于Java的配置

利用@Configuration注解来标识Java配置类

第4章:面向切面的Spring

    
    
        org.aspectj
        aspectjweaver
        1.8.10
    
    
        org.aspectj
        aspectjrt
        1.8.10
    
    
        aopalliance
        aopalliance
        1.0
    

在软件开发中,分布于应用中多处的功能被称为横切关注点。通常,这些横切关注点从概念上是与应用的业务逻辑相分离的。将这些横切关注点与业务逻辑相分离正是面向切面编程所要解决的。

(1)定义切点

execution(* spring.test.bean.Class.function(..)) && others

(2)在XML中声明切面


<beans -- 新添加 -->
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop 
     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    <bean
        id="poeticDuke"
        class="spring.test.bean.PoeticJuggler">
    bean>
    <bean
        id="audience"
        class="spring.test.bean.Audience">
    bean>
    <aop:config>
        <aop:aspect ref="audience">
            
            <aop:pointcut
                id="performance"
                expression="execution(* spring.test.bean.Performer.perform(..))" />
            <aop:before
                method="takeSeats"
                pointcut="execution(* spring.test.bean.Performer.perform(..))" /> 
            <aop:after-returning
                method="applaud" -- applaudaudience的方法 -->
                pointcut-ref="performance" />
        aop:aspect>
    aop:config>
beans>
  • 声明环绕通知
// Audience 类中定义此方法,ProceedingJoinPoint作为方法的入参
public void watchPerformance(ProceedingJoinPoint joinPoint) {
    try {
        // do something
        // 谨记必须调用proceed方法,否则本通知会阻塞被通知的方法,即perform()方法
        joinpoint.proceed();
        // do other things
    }
}
    <aop:config>
        <aop:aspect ref="audience">
            <aop:around
                method="watchPerformance()" --do something,然后调用perform(),再do other things -->
                pointcut="execution(* spring.test.bean.Performer.perform(..))" /> 
        aop:aspect>
    aop:config>
  • 为已有Bean引入接口
<aop:aspect>
    <aop:declare-parents
        -- 匹配已有的bean -->
        types-matching="spring.test.bean.Performer+"
        
        implement-interface="spring.test.bean.NewInterface"
        
        default-impl="spring.test.bean.InterfaceInstance"
    />
aop:aspect>

(3)基于注解的切面

@Aspect
public class Audience {
    @Pointcut("execution(* spring.test.bean.Performer.perform(..))")
    public void performance() {

    }

    @Before("performance()")
    public void takeSeats() {
        System.out.println("Take seat");
    }
}

<aop:aspectj-autoproxy />
  • 基于注解的同样可以
    • 注解环绕通知
    • 传递参数给所标注的通知
    • 引入新接口

Spring切面仍然只是基于代理的,而且限于通知方法的调用。如果需要的功能超过了Spring所支持的方法代理,那么可以考虑使用AspectJ,Spring只有简单功能的aop。

第5章:装配Bean

  • JDBC只提供了SQLException异常,以至发生异常不知道问题在哪。spring提供了多个数据访问异常,分别描述他们抛出时所对应的问题
  • 针对不同持久化平台,spring提供多个可选的模版
  • spring针对不同模版提供了对应的DAO支持类

(1)配置数据源

  • 使用JDNI数据源
    • 需要在web server中配置数据源,需作相应部署
  • 使用数据源连接池
    • 第三方依赖包中包含了两个数据源的实现类包,其一是Apache的DBCP,其二是 C3P0(推荐使用)
  • 基于JDBC驱动数据源
    • 没有使用连接池,项目中少用
<bean id="dataSource class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://ip:3306/zhihu" />
    <property name="username" value="root" />
    <property name="password" value="" />
bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource" />
bean>
<bean id="mysql" class="spring.test.db.Mysql">
    <property name="jdbcTemplate" ref="jdbcTemplate" />
bean>

(2)使用JDBC DAO支持类

  • DAO支持类中定义好了获取Jdbc模版的相应方法

(3)Java持久化API

  • spring还支持 java persistence API,JPA是一套规范,Hibernate,TopLink,JDO他们是一套产品,这些产品实现了这个JPA规范,JPA有点像JDBC,为各种不同的ORM技术提供一个统一的接口,方便把应用移植的不同的ORM技术上。

第6章:事务管理

Spring提供的事务管理:

  • 编码式
    • 对事务边界控制精确,但是Spring的编码式事务是侵入式的,需修改类的实现
  • 声明式
    • 通常情况下,事务需求不会要求很高的事务边界控制,故用的较多

(1)事务管理器

  • Spring并不直接管理事务,而是提供了多种事务管理器,将事务管理的职责委托给其他平台相关的事务实现


【读过的书,留下的迹】Spring实战(第3版)_第1张图片

example: JDBC事务

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
bean>

(2)声明式事务

  • 属性
    • 传播行为:新的事务应该被启动还是被挂起,或者方法是否要在事务环境中运行
    • 隔离级别:一个事务可能受其他并发事务影响的程度
    • 只读
    • 事务超时
    • 回滚规则


【读过的书,留下的迹】Spring实战(第3版)_第2张图片


【读过的书,留下的迹】Spring实战(第3版)_第3张图片

(3)在xml中定义事务

<tx:advice id="txAdvice" transaction-manager="yourManager">
    <tx:attributes>
        
        <tx:method name="save*" propagation="REQUIRED" />
        <tx:method name="*" propagation="SUPPORTS" read-only="true" />
    tx:attributes>
tx:advice>
<aop:config>
    
    <aop:advisor
        pointcut="execution(* *..SpitterService.*(..))"
        advice-ref="txAdvice" />
aop:config>

(4)在注解驱动中定义

<tx:annotation-driver transaction-manager="yourManager" />
@Transactional(propagation=Propagation.SUPPORTS, readOnly=true)
public class ServiceImpl implements Service {
...
    @Transactional(propagation=Propagation.REQUIRED, readOnly=false)
    public void addSomething() {
    }
}

第7章:使用Spring MVC

  • 与大多数基于Java的Web框架一样,Spring MVC所有的请求都会通过一个前端控制器Servlet——DispatcherServlet

(1)搭建Spring MVC

web.xml

<web-app>
  <display-name>Archetype Created Web Applicationdisplay-name>

  
  <servlet>
    
    <servlet-name>weiboservlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    servlet-class>
    <load-on-startup>1load-on-startup>
  servlet>
  <servlet-mapping>
    <servlet-name>weiboservlet-name>
    <url-pattern>/url-pattern>
  servlet-mapping>

web-app>

weibo-servlet.xml

    
    <mvc:resources
        mapping="/resources/**"
        location="/resources/" />

    
    <mvc:annotation-driven />
    <context:component-scan base-package="spring.test.mvc" />

    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        
        <property
            name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <property
            name="prefix"
            value="/WEB-INF/views/" />
        <property
            name="suffix"
            value=".jsp" />
    bean>

(2)基本控制器

@Controller
public class HomeController {
    public static final int DEFAULT_WEIBO_PER_PAGE = 25;

    // 映射路径
    @RequestMapping({"/", "/home"})
    public String showHomePage(Map model) {
        model.put("weibos", new WeiboHome());
        return "home";
    }
}

(3)控制器输入

@Controller
@RequestMapping("/weiboo") // 定义大的路径
public class Weiboo {
    @RequestMapping(value="/boo", method=GET) // 路径为/weiboo/boo?name=lin
    // 请求参数如果与下面的参数名一样,可省略@RequestParam("name")
    // model是spring自己定义的map,会根据addAttribute的类,定义key
    public String listWeiboo(@RequestParam("name") String name, Model model) {
        model.addAttribute("name", name);
        model.addAttribute("time", "2017");
        return "weiboo";
    }
}

weiboo.jsp


<%@ page isELIgnored="false" %>
<div>
    <h1>This is weiboo of ${name}h1>
    <h1>Time is ${time}h1>
div>

你可能感兴趣的:(读书笔记,spring,java)