目录

  1.开始Spring之旅(简介)

  2.装配Bean(IoC)

  3.创建切面(AOP)

  。。。

第一章:开始Spring之旅

  1.1 为什么使用Spring:简化了企业级系统开发。

    1.1.1 javaEE开发者的一天:EJB功能强大,即使简单的应用系统都需要各种组件的支持,使用较为复杂。

    1.1.2 Spring的承诺:

      1.好的设计比实现技术更重要

      2.通过接口松散耦合的JavaBean是一个很好的模型

      3.代码应该容易被测试

  1.2 Spring是什么:Spring是一个轻量级的IOC和AOP容器框架

    轻量级:1MB多的jar包源代码

    非侵入式:基于Spring开发系统中的对象一般不依赖于Spring框架中的类

    反向控制:创建一个对象时,需要在容器系统中寻找所对应的类,而反向控制,则是在容器启动实例化时,主动为引用的实例类注入依赖类对象

    面向切面:提取多种业务的共性,形成一种过滤效果,使开发者只需要关注具体的逻辑业务问题

    容器:可以管理系统中对象的生命周期与设置(BeanFactory/ApplicationContext)

    框架:通过XML文件配置组合

    spring组成模块:

      

  1.3 开始Spring之旅

//接口定义
package com.cys.test;
public interface GreetingService {
public void sayGreeting();
}
//具体实现类
package com.cys.test; public class GreetingServiceImpl implements GreetingService {
private String greeting;
public GreetingServiceImpl() {}
public GreetingServiceImpl(String greeting) {
this.greeting = greeting;
}
public void sayGreeting() {
System.out.println("GreetingServiceImpl [greeting=" + greeting + "]");
}
public void setGreeting(String greeting) {
this.greeting = greeting;
}
}
//主函数类
package com.cys.test; import java.io.FileInputStream;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory; public class HelloApp{
public static void main(String[] args) throws Exception{
BeanFactory factory = new XmlBeanFactory(new FileInputStream("spring-beans.xml"));
GreetingService greeting = (GreetingService)factory.getBean("greetingService");
greeting.sayGreeting();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- xml配置文件 -->
<beans>
<!-- 无参数构造 -->
<bean id="greetingService" class="com.cys.test.GreetingServiceImpl">
<property name="greeting" value="Hello World" />
</bean>
<!-- 带参数构造 -->
<bean id="greetingService" class="com.cys.test.GreetingServiceImpl">
<constructor-arg>
<value>Hello World</value>
</constructor-arg>
</bean>
</beans>

  1.4 理解反向控制(依赖注入):获得依赖对象的方式反转

  1.5 应用AOP:IoC使软件组件松散连接成为可能,AOP让你能够捕捉经常使用的功能,把该功能转化为组件

    

  1.6 Spring比较

    

  小结:

  

  

第二章:装配Bean

  2.1 容器是Spring框架的核心:BeanFactory、ApplicationFactory

    2.1.1 BeanFactory:Bean简单工厂管理模式

      常见实现类:XmlBeanFactory

        BeanFactory factory = new XmlBeanFactory(new FileInputStream("beans.xml"));

        MyBean myBean = factory.getBean("myBeanId");

    2.1.2 ApplicationFactory:提供更多附加的功能(文本信息解析工具、载入文件资源、注册监听器)

      常见实现类:ClassPathXmlApplicationFactory、FileSystemXmlApplicationFactory、XmlWebApplicationFactory

        ApplicationFactory factory = new ClassPathXmlApplicationFactory("beans.xml");

        ApplicationFactory factory = new FileSystemXmlApplicationFactory("c:/beans.xml");

        XmlWebApplicationFactory:见第八章

    2.1.3 Bean生命周期

  

    Bean工厂容器与ApplicationContext容器的唯一区别:ApplicationContext容器会调用ApplicationContextAware接口的setApplicationContext()方法

  2.2 基本配置(Beans.xml)

    2.2.1 xml配置:<beans><bean id="" class=""/><beans ...></beans>

    2.2.2 添加一个Bean

      bean属性:

        单实例与原型:singleton="true"--单实例(默认)  singleton="false"--原型(每次getBean(),获取的对象都是一个新的)

        实例化与销毁:init-method="name1"--初始化时调用name1()方法  destroy-method="name2"--销毁时调用name1()方法

    2.2.3 set属性注入

      基本类型注入(int、String、...):<property name="xxx"><value>xxx(值)</value></property>

      引入其他bean:<property name="xxx"><ref bean="xxx(beanId)"></property>(常用)、<property name="xxx"><bean class="" /></property>(不常用)

      List与数组:<property name="xxx"><list><value>xxx(值)</value><ref ...><...></list></property>(值可以是任意元素)

      Set:<property name="xxx"><set><value>xxx(值)</value><ref ...><...></set></property>(值可以是任意元素)

      Map:<property name="xxx"><map><entry key="xxx1"><value>xxx(值)</value></entry><entry key="xxx2"><ref ...></entry><entry key="..."><...></entry></map></property>(值可以是任意元素)

      Property:<property name="xxx"><prop key="xxx1">xxx(值)</prop><prop key="xxx2">xxx(值)</prop>...</property>(值只能是String类型,不需要<value>标签)

      设置null:<property name="xxx"><null/></property>(默认可以不设置,这是显示装配)

    2.2.4 构造函数注入

      与set同理,<property>改为<constructor-arg>,并提供了index、tyep属性

      index:参数序号,从0开始--<constructor-arg index="0"><value><ref ...>...</constructor-arg>  

      type:属性类型(java.lang.String)--<constructor-arg type="java.lang.String"><value><ref ...>...</constructor-arg>

      默认情况可以不设置,在多个参数类型相同时,为区分参数先后顺序,必须设置index属性

      set注入与构造函数注入区别:构造函数可以强制关联依赖关系,达到初始化一个完整可用的对象

  2.3 自动装配Bean(一般不考虑)

    。。。

  2.4 特殊bean:实现spring特定的接口,在bean生命周期的过程中处理bean信息

    2.4.1 对bean进行后处理:实例化后初始化前--初始化后

      接口:BeanPostProcessor

        覆盖方法(实例化后初始化前方法):postProcessBeforeInitialization(Object bean, String name)

        覆盖方法(初始化后方法):postProcessAfterInitialization

      注册bean:

        Bean工厂容器:factory.addBeanPostProcssor(BeanPostProcessor接口类的实现类)

        上下文容器:在xml配置文件里添加实现BeanPostProcessor接口的类bean即可,上下文容器会自动识别:<bean id="" class="" />

      spring框架自动BeanPostProcessor实现

        。。。

    2.4.2 对Bean工厂进行后处理:实例化之前,即容器加载bean配置文件定义,开始实例化每个bean之前

      接口:BeanFactoryPostProcessor

        覆盖方法(实例化之前):postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)

    2.4.3 分散配置:Spring容器定义bean信息集中在一个配置文件里,不利于维护和修改,容易形成硬性编码

      ApplicationContext上下文容器自带引用加载properties类型文件实现类:PropertyPlaceholderConfigurer

      在xml配置文件里添加以下代码,加载属性,可以使用${key}来获取properties属性文件所对应的值     

      <bean id="xxx" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

        <property name="location">

          <value>xxx.properties</value>

            <value>...</value>

        <property>

      </bean>

    2.4.4 属性类型编辑器:对参数值类型转换接收

      。。。

    2.4.5 解析文本信息

      。。。

    2.4.6 监听事件:ApplicationContext容器在生命周期中默认会触发许多事件

      触发事件:ContextCloseEvent--应用上下文关闭时触发  ContextRefreshedEvent--应用上下文初始化或刷新时触发  RequestHandledEvent--Web服务应用上下文中请求被处理后触发

        这个三个事件类都是抽象类org.springframework.context.ApplicationEvent的子类

      监听事件处理:实现org.springframework.context.ApplicationListener接口,实现onApplicationEvent方法,并在spring配置文件里注册bean

    2.4.7 设置触发事件

      。。。

    2.4.8 感知bean:用于获取bean属性信息

      常用接口:BeanNameAware--获取beanID  BeanFactoryAware--获取bean容器  ApplicationContextAware--获取bean容器

        bean类实现BeanNameAware接口,获取beanID值

          //声明属性,设置属性值,注册bean后,自动加载属性赋值          

          public class GetBeanName implements BeanNameAware{
            private String beanName;
            public void setBeanName(String beanName){
              this.beanName = beanName;
            }
          }

        bean类实现BeanFactoryAware接口,获取容器

          //声明属性,设置属性值,注册bean后,自动加载属性赋值

          public class GetBeanFactory implements BeanFactoryAware{
            private BeanFactory factory;
            public void setBeanFactory(BeanFactory factory){
              this.factory= factory;
            }
          }

        bean类实现ApplicationContextAware接口,获取容器

          //声明属性,设置属性值,注册bean后,自动加载属性赋值

          public class GetBeanFactory implements ApplicationContextAware{
            private ApplicationContext context;
            public void setApplicationContext(ApplicationContext context){
              this.context = context;
            }
          }

    

第三章:创建切面

  3.1 AOP介绍

    3.1.1 定义AOP术语:切面(Aspect)、连接点(Joinpotion)、通知(Advice)、切入点(Pointcut)、引入(Introduction)、目标对象(Target)、代理(Proxy)、织入(Weaving)

    3.2.2 Spring的AOP实现

        。。。

  3.2 创建通知

    

    3.2.1 前置通知:目标方法前执行

//创建通知实体类,实现前置通知接口,复写接口方法
public class WelcomeAdvice implements MethodBeforeAdvice{
//Method:目标方法
//args:目标方法参数列表
//target:目标对象
public void before(Method method, Object[] args, Object target){
    //具体通知逻辑业务
}
}
<!-- 配置文件 -->
<bean id="xxx1" class="目标对象" /> <bean id="xxx2" class="具体通知对象"> <bean id="xxx3" class="org.springframework.aop.framework.ProxyFactoryBean(代理对象)">
<property name="proxyInterfaces(目标对象实现的接口类)">
<value>xxx.xxxxx.xxxx.xxx4</value>
</property>
<property name="interceptorNames(通知列表)">
<list>
<value>xxx2</value>
...
</list>
</property>
<property name="target(目标对象)">
<value>xxx1</value>
</property>
</bean>

    3.2.2 后置通知:目标方法后执行

//创建通知实体类,实现后置通知接口,复写接口方法
public class ThankYouAdvice implements AfterReturningAdvice{
//returnValue:目标方法的返回值
//Method:目标方法
//args:目标方法参数列表
//target:目标对象
public void afterReturning(Object returnValue, Method method, Object[] args, Object target){
    //具体通知逻辑业务
}
}

    3.2.3 环绕通知:目标方法前后都行,但需要手动调用目标方法并返回值

//创建通知实体类,实现环绕通知接口,复写接口方法
public class OnePerCustomerInterceptor implements MethodInterceptor{
//MethodInterceptor:封装目标对象相关类
public Obeject invoke(MethodInvocation invocation){
  //手动调用目标方法,返回目标方法返回值
Obeject xxx = invocation.proceed();
//手动返回
return xxx;
}
}

    3.2.4 异常通知:调用目标方法抛出异常时执行

      实现ThrowsAdvice接口,并覆盖void afterThrowing(Throwable throwable)与void afterThrowing(Throwable throwable,  Method method, Object[] args, Object target)任意一个方法

    3.2.5 引入通知:给目标对象添加行为或属性

      。。。

  3.3 定义切入点:定义通知在那些地方应用

    3.3.1 在Spring中定义切入点

//切入点核心接口
public interface Poincut{
  //类过滤
  ClassFilter getClassFilter();
  //方法过滤
  MethodMatcher getMethodMatcher();
}
//类过滤接口
public interface ClassFilter{
//根据类名过滤
boolean maches(Class clazz);
}
//方法过滤接口
public interface MethodMatcher{
//判断是否目标方法是否需要通知
boolean maches(Method m, Class targetClass);
//如果maches返回true,则调用判断是静态通知还是动态通知
public boolean isRuntime();
//只有isRuntime返回true,则为动态通知,才会执行以下方法
public boolean maches(Method m, Class targetClass, Object[] args);
}

    提示:尽量使用静态通知,动态通知对性能会有消耗

    3.3.2 理解Advisor:通知与切入点整合接口类

//Advisor接口
public interface PointcutAdvisor{
//获取切入点类
Pointcut getPointcut();
//获取通知类
Advice getAdvice();
}

    3.3.3 使用Spring的静态切入点

      父类:StaticMethodMatcherPointcut

      常用子类(名称映射):NameMatchMethodPointcut

        映射方法:public void setMappedName(String), public void setMappedName(String[]);

      配置NameMatchMethodPointcut类型切入点:

<beans>
<bean id="xxx1" class="(目标实例类)"/> <bean id="xxx2" class="(通知类)"/> <!-- 定义切入点 -->
<bean id="xxx3" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<!-- 定义通知切入的规则 -->
<property name="mappedName">
<value>order*</value>
<!-- 不适用通配符,指定具体切入方法
<list>
<value>orderxxx1</value>
<value>orderxxx2</value>
</list>
-->
</property>
<!-- 绑定切入点的通知 -->
<property name="advice">
<ref bean="xxx2" />
</property>
</bean> <!-- 切面代理类 -->
<bean id="xxx4" class="org.springframework.aop.framework.ProxyFactoryBean(代理对象)">
<property name="proxyInterfaces(目标对象实现的接口类)">
<value>xxx.xxxxx.xxxx.xxx5</value>
</property>
<property name="interceptorNames(通知列表)">
<list>
<value>xxx3</value>
...
</list>
</property>
<property name="target(目标对象)">
<value>xxx1</value>
</property>
</bean>
</beans>

      规则表达式切入点:RegexpMethodPointcut

      配置RegexpMethodPointcut类型切入点:

<beans>
<bean id="xxx1" class="(目标实例类)"/> <bean id="xxx2" class="(通知类)"/> <!-- 定义切入点 -->
<bean id="xxx3" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!-- 定义通知切入的规则 -->
<property name="pattern">
<!-- 定义通知切入的规则:所有类以get开头,后面至少有一个字符,接着有By,再后面至少有一个字符 -->
<value>.*get.+By.+</value>
</property>
<!-- 绑定切入点的通知 -->
<property name="advice">
<ref bean="xxx2" />
</property>
</bean> <!-- 切面代理类 -->
<bean id="xxx4" class="org.springframework.aop.framework.ProxyFactoryBean(代理对象)">
<property name="proxyInterfaces(目标对象实现的接口类)">
<value>xxx.xxxxx.xxxx.xxx5</value>
</property>
<property name="interceptorNames(通知列表)">
<list>
<value>xxx3</value>
...
</list>
</property>
<property name="target(目标对象)">
<value>xxx1</value>
</property>
</bean>
</beans>

    3.3.4 动态切入点

      。。。

    3.3.5 切入点合并与交叉:通过切入点与切入点、对象、方法、等等的组合与交集形成新的切入点,创建一个实体类,编写参数切入点组合,通过属性配置bean注入切入点参数

      1.编写切入点组合工具类

//编写组合代码工具类
public class UnionPointcut implements Pointcut{
//声明合并的Pointcut实例
private Pointcut delegate;
//接口方法
public ClassFilter getClassFilter(){
return getDelegate().getClassFilter();
}
public MethodMatcher getMethodMatcher(){
return getDelegate().getMethodMatcher();
}
//声明异常
private Pointcut getDelegate(){
if(delegate == null){
throw new AopConfigException("No pointcuts have configured.");
}
return delegate;
}
//组合切入点的逻辑代码
public void setPointcuts(List pointcuts){
if(pointcuts == null || pointcuts.size() == 0){
throw new AopConfigException("Must have at least one Pointcut.");
}
}
delegate = (Pointcut)pointcuts.get(0);
for(int i = 1; i<pointcuts.size(); i++){
Pointcut pointcut = (Pointcut)pointcuts.get(i);
delegate = Pointcuts.union(delegate, pointcut);
}
}

      配置<bean id="xxx" class="xxx.xxx.UnionPointcut"><property name="pointcuts"><Lits><value>xxx</value>...</List></property></bean>

    2.编写切入点交集工具类:

      。。。

  3.4 创建引入切面:对已有的实体类添加行为或属性

    。。。

  3.5 ProxyFactoryBean详解

    常用属性:target、proxyInterfaces、interceptorNames

    

    

  3.6 自动代理:BeanNameAutoProxyCreator、DefaultAutoProxyCreator

    BeanNameAutoProxyCreator可以的代理类型:切入点、通知、拦截器,DefaultAutoProxyCreator只能代理切入点(Advisor)

    BeanNameAutoProxyCreator配置

<bean id="xxx1" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<!-- 正则表达式 -->
<value>*Service</value>
</list>
</property>
<property name="interceptorNames">
<value>xxx(切入点、通知、拦截器)</value>
</property>
</bean>

    DefaultAutoProxyCreator配置:

<bean id="xxx1" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref bean="xxx2(通知)">
</property>
<property name="pattern">
<value>.+Service\..+</value>
</property>
</bean>
<!-- 自动代理Advisor通知 -->
<bean id="xxx3" class="org.springframework.aop.framework.autoproxy.DefaultAutoProxyCreator"/>

  

  

    

Spirng+In+Action(Craig Walls Ryan Breidenbach)的更多相关文章

  1. SPRING IN ACTION 第4版笔记-第十一章Persisting data with object-relational mapping-005Spring-Data-JPA例子的代码

    一.结构 二.Repository层 1. package spittr.db; import java.util.List; import org.springframework.data.jpa. ...

  2. SPRING IN ACTION 第4版笔记-第十一章Persisting data with object-relational mapping-004JPA例子的代码

    一.结构 二.Repository层 1. package spittr.db; import java.util.List; import spittr.domain.Spitter; /** * ...

  3. SPRING IN ACTION 第4版笔记-第十一章Persisting data with object-relational mapping-001-使用Hibernate(@Inject、@EnableTransactionManagement、@Repository、PersistenceExceptionTranslationPostProcessor)

    一.结构 二.Repository层 1. package spittr.db; import java.util.List; import spittr.domain.Spitter; /** * ...

  4. SPRING IN ACTION 第4版笔记-第十章Hitting the database with spring and jdbc-002-本章的源代码

    0.结构 一.JDBC层 1. package spittr.db; import java.util.List; import spittr.domain.Spitter; /** * Reposi ...

  5. SPRING IN ACTION 第4版笔记-第九章Securing web applications-007-设置LDAP server比较密码(contextSource、root()、ldif()、)

    一.LDAP server在哪 By default, Spring Security’s LDAP authentication assumes that the LDAP server is li ...

  6. SPRING IN ACTION 第4版笔记-第六章RENDERING WEB VIEWS-006- 使用thymeleaf(TemplateResolver、SpringTemplateEngine、ThymeleafViewResolver、th:include、th:object、th:field="*{firstName}")

    一.在Spring中使用thymeleaf的步骤 1.配置 In order to use Thymeleaf with Spring, you’ll need to configure three ...

  7. SPRING IN ACTION 第4版笔记-第六章RENDERING WEB VIEWS-005- 使用ApacheTiles(TilesConfigurer、TilesViewResolver、<put-attribute>、<t:insertAttribute>)

    一. 1.定义TilesConfigurer.TilesViewResolver的bean 注意有tiles2和tiles3,这里使用tiles3 (1)java形式 package spittr.w ...

  8. Spring学习(三)——Spring中的依赖注入的方式

    [前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring.不知 ...

  9. Spring学习(一)——Spring中的依赖注入简介【转】

      [前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring. ...

随机推荐

  1. shell 日期加减运算

    比如今日是2012-04-22 $ date -d "+1 day" +%Y-%m-%d 2012-04-23   $ date -d "-1 day" +%Y ...

  2. log4j2.xml的例子

    项目中用到的一个log4j2.xml的配置文件: <?xml version="1.0" encoding="UTF-8"?> <!--设置l ...

  3. link_to嵌套

    = link_to theses_path, :class=>"btn" do .text-center 购买

  4. 项目中对模板和js,css文件进行压缩的处理类

    我们知道,在html的页面中,所有空格和换行符其实都会占据一定的空间,即使使用了gzip压缩,在传输过程中依然会浪费用户的流量和我们自己服务器的带宽,此脚本就是为了解决这个问题而诞生的. 请自行下载G ...

  5. php基本语法与函数

    1.标记与注释 <?php 代码 ?> 用/*  */注释一段代码,  用 // 注释一行代码   /**    */文档注释 注意:若php下面只有php代码没有别的代码,那么最好不要加 ...

  6. 写出pythonic的python代码

    http://www.cnblogs.com/dadadechengzi/p/6226071.html 1,列表推导(没当要对序列中的内容进行循环处理时,就应该尝试使用列表推倒) 在python中编写 ...

  7. [原创]java WEB学习笔记12:一个简单的serlet连接数据库实验

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  8. vi/vim滚动屏幕

    VIM帮助文档如是说 Q_sc Scrolling CTRL-E N CTRL-E window N lines downwards (default: 1) CTRL-D N CTRL-D wind ...

  9. mysql备份,知识点

    1.mysql错误日志 show variables like '%log_error%'; my.cnf中log-error=/tmp/SZDB.err 开启 tail -f 错误日志  观察mys ...

  10. 解决css的float父div没有高度

    在做页面设计常会碰到css的float父div没有高度的情况,HTML代码设计 <div class='box'> <div class='float_left'></d ...