Spring配置

Spring:

--1 使用jar包:
spring.jar
commons-logging.jar

使用aop
aspectjweaver.jar
aspectjrt.jar
cglib-nodep-2.1_3.jar

使用注解:
common-annotations.jar


--2 实例化容器:

ApplicationContext ctx =
new ClasspathXmlApplicationContext("applicationContext.xml");

ApplicationContext context=
new FileSystemXmlApplicationContext(new String[]{"d:\\beans.xml"});

--3 使用ContextLoaderListener
从ServletContext取得web.xml中初始化的ApplicationContext

首先在web.xml中配置listener。

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:spring/*.xml</param-value>
</context-param>
<listener>
    <listener-class>
     org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>
            

然后从ServletContext中获得ApplicationContext。

ApplicationContext context =
WebApplicationContextUtils.getWebApplicationContext(application);          

对于无法获得ServletContext的环境,最好自定义一个listener,
将生成的ApplicationContext放入一个单例中,以便日后使用。

--Spring配置要点:
(1) 在xml中使用spring-2.x的DTD。

   <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
   "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

   相比schema真是方便了很多,这样可以在必须使用特定schema的时候,再让他重装上阵。

   spring-2.x中去掉了singleton属性,使用scope属性做替代。
   如果还想使用singleton属性,必须配置成spring-1.x格式的DTD。

   提示:
   spring中已不再推荐使用singleton属性,因为单例在多jvm,
   远程调用,集群的情况下难以掌控,还是为实例指明生存的scope比较好。

(2)default-lazy-init

   懒惰加载,系统启动的时候并不加载xml中定义的bean,
   而是等到实际调用的时候才去加载,这样可以缩短系统初始化时间,
   在测试系统部分功能的情况下有极大的好处。

   注意,PropertityPlaceHolderConfigurer,springmvc,
   xfire,quartz等的配置文件不能声明为懒惰加载,否则会出问题。

(3) default-autowire="byName"
    按名称自动绑定。设置了这个,只要定义bean的时候名称与需要绑定的属性名相同,
    在实例化对象的时候,spring就会将这些实例自动绑定,
    不需要再去声明绑定哪些property。减少xml代码量,使得结构更清晰。

    在使用compass的时候要注意,不能使用按名称自动绑定,
    会自动为compass绑定dataSource导致错误。

(4) import  (????)
    将xml统一放在classpath下,这样更有利于进行单元测试,
    对于多个模块的xml使用import进行导入,层次更清晰。

    <import resource="classpath:jbpm/applicationContext-jbpm4.xml"/>
            
(5) CharacterEncodingFilter
    spring提供的编码过滤器,好处一是不用自己动手写了,
    好处二是保证每次请求只过滤一次。配置如下:(web.xml)

    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>
        org.springframework.web.filter.CharacterEncodingFilter
        </filter-class>
        <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
            

(6) IntrospectorCleanupListener
    spring提供的监听器,避免Struts,Quartz的内存泄露导致ClassLoader不能加载。
    配置如下:(web.xml)

    <listener>
    <listener-class>
    org.springframework.web.util.IntrospectorCleanupListener
    </listener-class>
    </listener>
            

(5) PropertyPlaceholderConfigurer
   读取properties中的变量,在xml中可以通过${变量名}的方式调用。配置如下:

    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
        <list>
            <value>classpath*:conf/jdbc.properties</value>
        </list>
        </property>
    </bean>

   <bean id="userManager" class="com.family168.manager.UserManager">
        <property name="username" value="${jdbc.username}"/>
   </bean>

  解析:jdbc.properties文件,内有对应的(key)username配置。

(6)PropertyOverrideConfigurer

   与PropertyPlaceholderConfigurer不同,
   PropertyOverrideConfigurer会在ApplicationContext初始化后,
   根据properties中的定义,修改对应属性的值。

   配置如下:

   <bean id="testPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
       <property name="locations" value="classpath*:override.properties"/>
       <property name="ignoreInvalidKeys" value="true"/>
   </bean>
            

    用来在测试环境下覆盖已有的配置,比如在override.properties中
    有userManager.username=111,那么id="userManager"的bean的username属性
    就会被修改为111。


(7)  Spring-2.x对AOP和事务管理的简化配置:

    1. 首先要使用schema

    <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"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
                
     
    2.然后要声明标记(不知道是不是必要的)

    <!-- 支持annotation @Transactional 标记 -->
    <tx:annotation-driven/>

    <!-- 支持annotation @AspectJ 标记-->
    <aop:aspectj-autoproxy/>

    3. 配置aop

    <aop:config proxy-target-class="true">
        <aop:advisor pointcut="execution(* com.family168.manager..*Manager.*(..))" advice-ref="txAdvice"/>
    </aop:config>
                
    注意:
    name-pattern千万不要写成*..*Manager ,
    这样子会把所有第三方类库的Manager比如Spring的PlatformTranstationManager
    也加入aop,非常危险。所以最好还是加上项目的package前缀,
    如"com.family168.manager..*Manager"

    因为有*,会修饰所有方法,有些hibernateTemplate的final的方法不能被cglib修改,
    会抛warning,无害。事务定义一般默认的PROPAGATION_REQUIRED即可,
    另提供的几个选择很少使用。值得注意的是一个PROPAGATION_NESTED,
    嵌入式事务的意义在于多级事务,如果出错只rollback子事务自己,不rollback主事务的所有操作。
    这需要JDBC3.0 SavePoint功能的支持。 而一般service间互相嵌入调用时,
    如果都定义为PROPAGATION_REQUIRED,有其中一个操作出错,rollback全部操作。
----------------
    4  配置txAdvice处理事务

    <tx:advice id="txAdvice">
        <tx:attributes>
        <tx:method name="get*" read-only="true"/>
        <tx:method name="find*" read-only="true"/>
        <tx:method name="pagedQuery*" read-only="true"/>
        <tx:method name="load*" read-only="true"/>
        <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>
                
    解析:

    tx这个命名空间会要求咱们提供一个名字为transactionManager的bean,用这个来作为默认的事务管理器。
    Spring参考文档 7.3 chema-based AOP support 提供了aspect,advisor,advide三种组装方法的解释,
    其中aspect是aspectJ原装,但稍复杂,这里唯一有点难懂的是pointcut里的语法,其实也很好学,
    Spring参考文档7.2.3.4里有完整说明 ,其实一排子过去是:
    
   

     execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
         throws-pattern?)

    modifiers-pattern:(public/protected)  可以不填
    ret-type-pattern:返回值可任意
    declaring-type-pattern 可以不填
    name-pattern  路径
    param-pattern  参数
    throws-pattern    可以不填

     eg1:
    //返回值任意,com.family168.manager路径下的,类名结尾为Manager类的任意参数类型方法
    * com.family168.manager..*Manager.*(..)
   
    eg2:
    execution(* *..BookManager.save(..))
    第一颗* //ret-type-pattern 返回值可任意,


    eg2:
    *..*Manager //任意Package里的以Manager结尾的类。
    
    eg3:
    如果写成com.xyz.service.* //com.xyz.service下的任意类

    eg4:
    com.xyz.service..* com.xyz.service//com.xyz.service及其子package下的任意类

    save代表save方法,也可以写save* 代表saveBook()等方法

    (..) 匹配0个参数或者多个参数的,任意类型

    (x,..) 第一个参数的类型必须是X

    (x,*,*,s,..) 匹配至少4个参数,第一个参数必须是x类型,
    第二个和第三个参数可以任意,第四个必须是s类型。
    
--------------------
(8) Spring中的零配置

    其实也不是完全的零配置,我们需要在xml中制定规范,然后在java中使用注解进行标注。

    首先要在xml中配置如下标记:

    <context:component-scan base-package="com.family168.manager" />
        

    这里需要使用Spring的schema命名空间进行配置,例子中使用的是springside中提供的例子,
    指定了默认在哪个包下查找需要进行注入的类。在Service类中使用@Service注释,
    Dao类中使用@Repository注释,通过pacakge扫描加入Spring的applicationContext。

    在私有属性或注入方法(不需要严格按setter命名)上 使用@Autowired 注释 进行byType注入,
    如果需要byName注入,增加@Qualifier注释。另@auwowired默认隐含了@Required特性

    使用@Required注释非@Autowired的属性,保证autowired下对象必然被注入,
    如果对象没有被注入则报错。使用JSR250的@PostConstruct来定义在执行完
    所有setter注入后必须执行的函数,比以往的实现接口或者在applicationContext.xml中
    配置init-method的方式更为标准。

    为提高效率,还是需要在xml中默认配置default-lazy-load和default-autowire byName。
                 
------------------------
(9)  Spring中的资源访问(????)

    1.  ResourceLoader
    ResourceLoader 可以获得ClassPath, File,URL中的文件,返回类型为Resource的统一资源定义。
    ApplicationContext中就拥有ResourceLoader。
    实现resourceLoaderAware接口可以获得ResourceLoader。

    2. ResourcePatternResolver
    ResourcePatternResolver 是ResourceLoader的升级版子接口,能解决ant-style的文件模糊批量定义,
    如applicationContext-*.xml。

    ApplicationContext中的ResourceLoader其实是ResourcePatternResolver ,
    可以通过强制转型获得,友好一点的做法是使用ResourcePatternUtils来转换。

    public class RescManager implements InitializingBean, BeanNameAware,
        ResourceLoaderAware {
        private ResourceLoader resourceLoader;

        public void demo() throws IOException {
        ResourcePatternResolver resolver = ResourcePatternUtils
            .getResourcePatternResolver(resourceLoader);
        Resource[] rescs = resolver.getResources(
            "classpath*:spring/applicationContext*.xml");
        System.out.println(rescs);
        }
    }
            
-------------------------------
(10)Spring的微内核与FactoryBean扩展机制
 1. 微内核的功能
  1.1. DI(依赖注入)与Singleton管理

    利用POJO setter的DI机制,估计每位同学随手都能写一个简单版本,不多说了。
    Singleton管理说白了就是先到一个map中按id找找看有没有已存在的实例。

  1.2. BeanName与BeanFactory注入

     除了DI注入的属性,微内核还有什么能卖给POJO呢?就是Bean在xml 定义里的id和BeanFactory自己了。
     卖的机制是让POJO 实现 BeanNameAware和BeanFactoryAware接口。
     BeanFactory用 if(pojo instance of BeanFactoryAware)判断到POJO需要注入BeanFactory,
     就调用setBeanFactory(this)将自己注入。

  1.3. DI后的初始化函数调用

     比如属性A,B注入之后,需要同时根据A和B来对A,B进行加工或者装配一个内部属性C,
     这样就需要在所有属性注入后再跑一个init()函数。

     Spring提供两种方式:
     一种是和上面的原理一样,实现InitializingBean接口的afterPropertiesSet()函数供Spring调用。
     一种是在xml定义文件里面自行定义init函数名。

    懒得每次在xml文件里定义的就采用第1种方式,不想与spring耦合的pojo就采用第2种方式。
    本来就是为了扩展Spring而存在的FactoryBean多采用第一种。

    所谓微内核,就是仅提供以上三种功能的DI容器。
    但作为轻量级容器,还需要以下两种方式,向容器内的POJO 附加各种服务。

 2. FactoryBean扩展机制

Spring的AOP、ORM、事务管理、JMX、Quartz、Remoting、Freemarker、Velocity,
都靠FacotryBean的扩展,FacotryBean几乎遍布地上:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"/>
<bean id="baseDAOService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"/>
            

这原理说出来好简单,所有FactoryBean 实现FactoryBean接口的getObject()函数。
Spring容器getBean(id)时见到bean的定义是普通class时,就会构造该class的实例来获得bean,
而如果发现是FactoryBean接口的实例时,就通过调用它的getObject()函数来获得bean,
仅此而以.......可见,很重要的思想,可以用很简单的设计来实现。


 3. Bean Post-Processor扩展机制(???)

如果说FactoryBean 是一种Factory、Wrapper式的扩展,
Bean Post-Processor就是另一种AOP、visitor式的机制,所以也多用于spring的AOP架构。

Post-Processor的原理就是BeanFactory在前文里的调用afterPropertiesSet()/init-method前后,
调用在工厂里注册了的post-processor的postProcessBeforeInitialization()和postProcessAfterInitialization()。

那怎么注册登记呢?又分请不请礼仪公司两类。
如果是ApplicationContext,你把继承BeanPostProcessor 的bean往xml里一搁就行了,
application context自会打理。如果是BeanFacotry,就要显式的注册,代码大概像:

XmlBeanFactory factory = new XmlBeanFactory("C:/beans.xml");
BeanPostLogger logger = new BeanPostLogger();
factory.addBeanPostProcessor(logger);
            
           
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值