‘Spring实践’ 分类下的所有文章
2010十月2

getHibernateTemplate().find(queryString, propertyValue)

Spring实践 评论关闭

public List find(String queryString, Object value), 据传来的sql:queryString,及为sql语句中”?“指定的值value进行查询
返回结果为List
注:即使查询无数据,返回的List也不是null, 而是数据个数为0
因无论数据存不存在,总会创建一个List对象返回,可判断是否有数据的方法为:
if ( l.size > 0 ) 不用再加 ( l !=null && l.size >0 )
或( ! l.isEmpty ) 同样不用再加 l != null 判断

2010十月2

Spring中bean的作用域

Spring实践 评论关闭
Spring中bean的作用域

在spring2.0之前bean只有2种作用域即:singleton(单例)、non-singleton(也称 prototype), Spring2.0以后,增加了session、request、global session三种专用于Web应用程序上下文的Bean。因此,默认情况下Spring2.0现在有五种类型的Bean。当然,Spring2.0对 Bean的类型的设计进行了重构,并设计出灵活的Bean类型支持,理论上可以有无数多种类型的Bean,用户可以根据自己的需要,增加新的Bean类型,满足实际应用需求。

1、singleton作用域(缺省)
当一个bean的作用域设置为singleton, 那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。换言之,当把一个bean定义设置为singleton作用域时,Spring IOC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的后续请求和引用都将返回被缓存的对象实例,这里要注意的是singleton作用域和GOF设计模式中的单例是完全不同的,单例设计模式表示一个ClassLoader中只有一个class存在,而这里的singleton则表示一个容器对应一个bean,也就是说当一个bean被标识为singleton时候,spring的IOC容器中只会存在一个该bean。
配置实例:

或者


2、prototype
prototype作用域部署的bean,每一次请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)都会产生一个新的bean实例,相当一个new的操作,对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责,容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,而对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责。(让Spring容器释放被singleton作用域bean占用资源的一种可行方式是,通过使用 bean的后置处理器,该处理器持有要被清除的bean的引用。)
配置实例:

或者


3、request
request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效。
request、session、global session使用的时候首先要在web.xml中做如下配置:

如果你使用的是Servlet 2.4及以上的web容器,那么你仅需要在web应用的XML声明文件web.xml中增加下述ContextListener即可:

...

org.springframework.web.context.request.RequestContextListener

...


,如果是Servlet2.4以前的web容器,那么你要使用一个javax.servlet.Filter的实现:

..

requestContextFilter
org.springframework.web.filter.RequestContextFilter


requestContextFilter
/*

...


接着既可以配置bean的作用域了:


4、session
session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效,配置实例:
配置实例:
和request配置实例的前提一样,配置好web启动文件就可以如下配置:


5、global session
global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局Session的概念,它被所有构成某个 portlet web应用的各种不同的portlet所共享。在global session作用域中定义的bean被限定于全局portlet Session的生命周期范围内。如果你在web中使用global session作用域来标识bean,那么web会自动当成session类型来使用。
配置实例:
和request配置实例的前提一样,配置好web启动文件就可以如下配置:


6、自定义bean装配作用域
在spring2.0中作用域是可以任意扩展的,你可以自定义作用域,甚至你也可以重新定义已有的作用域(但是你不能覆盖singleton和 prototype),spring的作用域由接口org.springframework.beans.factory.config.Scope来定义,自定义自己的作用域只要实现该接口即可,下面给个实例:
我们建立一个线程的scope,该scope在表示一个线程中有效,代码如下:
publicclass MyScope implements Scope {
privatefinal ThreadLocal threadScope = new ThreadLocal() {
  protected Object initialValue(){
     returnnew HashMap();
   }
};
public Object get(String name, ObjectFactory objectFactory) {
 Map scope = (Map) threadScope.get();
 Object object = scope.get(name);
if(object==null){
   object = objectFactory.getObject();
   scope.put(name, object);
 }
return object;
}
public Object remove(String name){
 Map scope = (Map) threadScope.get();
return scope.remove(name);
}
publicvoid registerDestructionCallback(String name, Runnable callback) {
}
public String getConversationId() {
// TODO Auto-generated method stub
returnnull;
}
   }
2010十月2

insert时检查重复值

Spring实践 评论关闭

Spring提供了一个 数据完整性异常,当进行insert操作时,若数据库中已存在此记录(主键相同),若某一字段在数据库中设置了不能为空,但在实际操作时却传入了null值,则就会抛出此异常,对其进行捕获,就可以得到信息,不用事先进行查询,再进行insert,直接捕获此异常并进行处理即可。
import org.springframework.dao.DataIntegrityViolationException;

try {
??????? dao.insertWords(obj);
??? } catch (DataIntegrityViolationException e) {
??? throw new Exception(“数据完整性冲突,请查看表结构是否存在问题!”);
??? }

2010十月2

The prefix “aop” for element “aop:config” is not bound

Spring实践 评论关闭

在XML中配置<aop:config>时出现此错误是因为:
使用<aop:config/> 标签,需要给Spring 配置文件中引入基于xml schema 的Spring AOP 命名空间:
<beans>中要加入“xmlns:aop”的命名申明,并在“xsi:schemaLocation”中指定aop配置的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
xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
??????????????? http://www.springframework.org/schema/aop
??????????????? http://www.springframework.org/schema/aop/spring-aop.xsd“>

2010十月2

AspectJ AOP实现

Spring实践 评论关闭

Spring AspectJ方式提供了在代码中进行AOP的方式,宜于集中化管理PointCut,不用再写好代码后,在xml中配置一大串。
AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件.

AspectJ语法

通配符

*? 表示任何数量的字符,除了.
.. 表示任何数量的字符包括任何数量的.
+? 描述指定类型的任何子类或者子接口???
!? 排除
||和&& 或,与

例:
java.*.Date???? 类型Date在任何直接的java子包中,如ava.util.Date和java.sql.Date
javax..*Model+? 所有javax包或者子包中以Model结尾的类型和其所有子类,如TableModel,TreeModel。
!vector???????????????????????????? 所有除了Vector的类型
Vector|| Hashtable????????????? Vector或者Hashtable类型
!public static * banking..*.*
所有的非public static 属性,在banking的包或者子包中
一,注解实现方式:

1,实现类
package com.lvjian.aop;

import java.util.Date;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect??? //指定下面的类为Aspect
public class Log {
Date date = new Date();
@Before(“execution( * *.update(..))”)???????? //任意类有update方法执行前执行logUpdate方法
??????????????????? //@Before(“execution( * *.update(..))”)? 前一个* 为update的返回类型,后一个 * 为类的名称
public void logUpdate(){
System.out.println( “begin update at ” + date.getTime() );
}

}

2,在applicationContext.xml像配置普通bean一样配置此类
<bean id=”logAspect”
</bean>

注:1,要在applicationContext.xml 加入对AspectJ的支持
<bean />
或<aop:aspectj-autoproxy/>

2, 注解有:
(1)Pointcut 当@Before(“execution( * *.update(..))”)? 多时,execution就会类同,这是切面,可定义一切面Pointcut解决。
???? @Pointcut(“execution( * *.update(..))”)
??????? public void pc(){???
??????????? System.out.println( “@Pointcut!!! “);??
????? }

???? @Before(value=”pc()”)
?????? public void logChange(){
?????????? System.out.println( “change!!! ” + date.getTime() );
}
(2)传统aop 增强类型有MethodBeforeAdvice,AfterReturningAdvice,MethodInterceptor,ThrowsAdvice等接口,对应的注解为:MethodBeforeAdvice? ??? @Before
??????? AfterReturningAdvice? ??? @AfterReturning
??????? MethodInterceptor????? ??? @Around
??????? ThrowsAdvice??????????? ??? @AfterThrowing
??????????????????????????????????????????????? @After :无论方法以何种方式结束,都会执行(类似于finally)
???????
?应用:
????
import java.util.Date;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class Log {
Date date = new Date();
@Before(“execution( * *.update(..))”)
public void logUpdate(){
System.out.println( “begin update at ” + date.getTime() );
}

@Pointcut(“execution( * *.update(..))”)
public void pc(){???
System.out.println( “@Pointcut!!! “);

}

@Before(value=”pc()”)
public void logChange(){
System.out.println( “before change!!! “? );
}

@AfterReturning(value=”pc()”)
public void AfterlogChange(){
System.out.println( “after!!! “? );
}

@Around(value=”pc()”)
public Object AroundlogChange( ProceedingJoinPoint point ) throws Throwable{
System.out.println( “around before “? );
Object re = point.proceed();
System.out.println( “around after “? );
return re;
}

@After(value=”pc()”)
public void AfterlogChange() {
System.out.println( “After ?? finally “? );
}
}
(3)注解对监听方法的操作:
1) 在形参中定义org.aspectj.lang.JoinPoint类型的参数,用些来访问方法。(注:@Around 用的是是ProceedingJoinPoint,它是org.aspectj.lang.JoinPoint的一个子类)
???
??? JoinPoint 方法有:
????? getArgs() :? ? 返回方法形参
????? getThis() :? ? 返回代理对象
????? getTarget() :返回目标
????? getSignature() :返回正在被通知的方法相关信息
????? toString() : 打印出正在被通知的方法的有用信息
@Before(value=”pc()”)
public void logChange( JoinPoint jp ){

System.out.println( “toString? ” + jp.toString()? );
}

2) 获取方法的参数
? getArgs() :? ? 返回方法形参

? @AfterReturning(“execution( * *.admin(..))&&args(userName,..)”)?? //args与类平行
? public void AfterReturninglogAdmin( String userName ){
????? System.out.println( “after admin !!! ” + userName );
}
二,XML配置实现方式:
1, 修改xml的头部,让其支持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-2.0.xsd
??????????????? http://www.springframework.org/schema/aop
??????????????? http://www.springframework.org/schema/aop/spring-aop.xsd“>

2,在XML中配置:
<aop:config>

<aop:aspect id=”log” ref=”logXML”>
<aop:pointcut id=”update” expression=”execution( * *.XMLBefore())” />
<aop:before pointcut-ref=”update”? method=”logUpdate” />
</aop:aspect>

</aop:config>

注: 要去掉用传统方式实现的自动代理AutoProxyCreator 如:
<bean id=”autoPghroxyCreator”?>
</bean>

2010十月2

传统AOP实现

Spring实践 评论关闭

1,完成方法的增强
实现MethodBeforeAdvice,AfterReturningAdvice,MethodInterceptor,ThrowsAdvice等接口
MethodBeforeAdvice,? 在方法调用前执行 before( Method m, Object[] arg1, Object arg2)
AfterReturningAdvice, 在方法调用后执行 afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3)
MethodInterceptor,在process()前后执行,invoke(MethodInvocation mi)
ThrowsAdvice 当方法抛出异常时执行,afterThrowing(Exception ex)

public class LoginBeforeAop implements MethodBeforeAdvice,AfterReturningAdvice,MethodInterceptor {

public void before( Method m, Object[] arg1, Object arg2)
throws Throwable {
System.out.println( m.getName() + ” ” + ” before ———— ” );

}

public void afterReturning(Object arg0, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
// TODO Auto-generated method stub
System.out.println(? ” end ———— ” );
}

public Object invoke(MethodInvocation mi) throws Throwable {
//在方法执行前最早执行,在方法执行后最后执行
// TODO Auto-generated method stub
System.out.println(“method “+mi.getMethod()+” is called on “+ mi.getThis()+” with args “+(mi.getArguments()));
Object ret = mi.proceed();
System.out.println( “methodInterceptor after “);
return ret;?? //注:若没有返回ret,调用会出错
}

2,实现自己的业务类与相应的接口,抽象类等。
如: LoginDaoInf,? LoginDaoAbst,? LoginDaoImpl,????

3, 将增强与业务类对应起来

在applicationContext.xml中配置:??
//业务类
<bean id=”loginDaoImpl”></bean>
//增强类
<bean id=”loginDaoAD”></bean>

//业务类与增强类装配
<bean id=”loginDaoInf”>
//指定业务类
<property name=”target” ref = “loginDaoImpl” />
//指定增强
<property name=”interceptorNames”>
<list>
<value>loginDaoAD</value>? //注,可指定多个增强
</list>
</property>
</bean>???

注: (1) 对指定的方法应用增强。? 实现方式:增强advisor配置
上述的配置方法会对一特定类的所有方法进行增强,若想对该类指定的方法进行增强,要配置一个advisor
让它包含advice,之后在业务类与增强类装配时用advisor代替advice即可。
??? (advice 建议,advisor顾问,建议高级形式就是顾问)

配置时class为NameMatchMethodPointcutAdvisor
<bean id=”loginDaoADR”>
<property name = “mappedNames” >
<list>
<value>check*</value>
<value>show</value>
??????????????? //对类以check开头的方法及show方法应用增强,增强用advice property指定,而是哪个类则
??????????????? //要在装配时才能确定。
</list>
</property>
<property name=”advice” ref=”loginDaoAD”></property>? //可看出:advisor = adivce + poingcut
</bean>

(2) 对指定的多个类一次指定增强。??? 实现方式:改变增强与业务类的装配方式。

1) BeanNameAutoProxyCreator方式

<bean id=”loginDaoInf”>
<bean id=”AllAuto”>
??? <property name=”beanNames” >
??????? <list>??????????????????? //指定为哪些类应用增强
??????????? <value>*DaoInf</value>
??????? </list>
??? </property>
??? <property name=”interceptorNames”>
??????? <list>????????????????? //指定应用的增强,advice或advisor
??????????? <value>loginDaoAD</value>
??????? </list>
??? </property>
</bean>

(3)自动对bean应用适合的增强(查找增强时只查找advisor,不用advice,因advice不能指定方法),即当bean方法若out()执行时,就在配置文件中的所有advisor中查找,若advisor有针对out方法的配置,如:
????????????? <property name = “mappedNames” >
??????????????????????? <list>
????????????????????????????? <value>out</value>
?????????????????????? </list
?????????????? </property>
就对此方法应用增强。

这种自动增强增强的实现方式如下:
在配置文件中加入:
<bean id=”autoProxyCreator”
??>
</bean>
就自动完成方法增强的侦测!

2010十月2

AOP 含义

Spring实践 评论关闭

AOP:
A advice 增强,指实现注入的代码
P Pointcut 切面,指对哪些类,哪些方法应用增强。

2010十月2

AOP

?所谓AOP,即面向方面编程(Aspect Oriented Programming),方面(Aspect)”它就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。它的作用更多地是关注于系统的某一方面

?? “设计模式”的触角始终在接口与抽象中大做文章,而对于对象内部则无能为力。AOP利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的行为封装到一个可重用模块,并将其名为“Aspect”

??? Spring AOP实现AOP技术从本质上来讲,是利用了JDK提供的动态代理技术。而从实际的实现方式来看,则是利用了IoC(Inversion of Control,反转模式)机制,同时采用了AOP联盟(AOP Alliance)的通用AOP接口。首先,Spring AOP通过xml配置文件配置了pointcut,并利用Interceptor(拦截机)作为设定的触发条件。Interceptor是由用户自定义的,它相当于是AOP中的advice,但该Interceptor需要实现AOP联盟的通用AOP接口,例如 org.aopalliance.intercept.MethodInterceptor。最后定义一个Spring AOP ProxyFactory用于加载执行AOP组件,并利用IoC机制将advice注入到接口以及实现类中。

?Spring AOP研究

Spring AOP使用纯Java实现,不需要特别的编译过程,也不需要控制类装载层次

。与JBoss AOP相同,它仍然利用了拦截器完成对方法的拦截。然而,Spring AOP

实现AOP的主要技术却主要来自于AOP联盟,如拦截器应实现

org.aopalliance.intercept.MethodInterceptor 接口,而所有advice必须实现

org.aopalliance.aop.Advice标签接口。此外,Spring实现AOP的目标也不同于其

他大部分AOP框架,它的目标不是提供及其完善的AOP实现,而是提供一个和

Spring IoC紧密整合的AOP实现,帮助解决企业应用中的常见问题。因此,Spring

AOP的功能通常是和Spring IoC容器联合使用的。AOP Advice是用普通的bean定义

语法来定义的,Advice和pointcut本身由Spring IoC 管理。这是一个重要的其他

AOP实现的区别。

3.2.3.1 切入点(pointcut)

Spring的切入点模型能够使pointcut独立于advice类型被重用。同样的pointcut

有可能接受不同的advice。将 Pointcut接口分成两个部分有利于重用类和方法的

匹配部分,并且组合细粒度的操作(如和另一个方法匹配器执行一个“并”的操

作)。

在Spring的切入点中,org.springframework.aop.Pointcut接口是重要的接口,

它用来指定通知到特定的类和方法目标。完整的接口定义如下:
public interface Pointcut
{
??? ClassFilter getClassFilter();
??? MethodMatcher getMethodMatcher();
}

ClassFilte类型也是一个接口,该接口被用来将切入点限制到一个给定的目标类

的集合。 如果matches()永远返回true,所有的目标类都将被匹配。
public interface ClassFilter
{
??? boolean matches(Class clazz);
}

MethodMatcher接口通常更加重要。完整的接口定义如下:
public interface MethodMatcher
{
??? boolean matches(Method m, Class targetClass);
??? boolean matches(Method m, Class targetClass, Object[] args);
??? boolean isRuntime();
}

matches(Method, Class) 方法被用来测试这个切入点是否匹配目标类的给定方法

。这个测试可以在AOP代理创建的时候执行,避免在所有方法调用时都需要进行测

试。如果2个参数的matches()方法对某个方法返回true,并且MethodMatcher的

isRuntime()也返回true,那么3个参数的matches()方法将在每次方法调用的时候

被调用。这使切入点能够在目标advice被执行之前立即查看传递给方法调用的参

数。由于大部分 MethodMatcher都是静态的,意味着isRuntime()方法会返回

false。此种情况下,3个参数的matches()方法永远不会被调用。

Spring AOP提供了几个实用的切入点实现,其中较为常用的是正则表达式切入点

:org.springframework.aop.support.RegexpMethodPointcut,它使用Perl 5的

正则表达式的语法。使用这个类你可以定义一个模式的列表。如果任何一个匹配

,那个切入点将被计算成 true。用法如下:
<bean id=”settersAndAbsquatulatePointcut”
???>
??? <property name=”patterns”>
??????? <list>
??????????? <value>.*get.*</value>
??????????? <value>.*absquatulate</value>
??????? </list>
??? </property>
</bean>

不过,更多情况下是直接使用RegexpMethodPointcut一个实用子类:

RegexpMethodPointcutAdvisor。它允许我们同时引用一个advice(在Spring AOP

中,advice可以是拦截器,也可以是before advice,throws advice等)。这就简

化了bean的装配,因为一个bean可以同时当作pointcut和advice,如下所示:
<bean id=”myPointcutAdvisor”

class=”org.springframework.aop.support.RegexpMethodPointcutAdvisor”>
??? <property name=”advice”>
??????? <ref local=”MyInterceptor” />
??? </property>
??? <property name=”patterns”>
??????? <list>
??????????? <value>.*save.*</value>
??????????? <value>.*do.*</value>
??????? </list>
??? </property>
</bean>

注意配置文件中的myPointcutAdvisor,在Spring AOP中,一个advisor就是一个

aspect完整的模块化表示。通过advisor,可以将pointcut和advice(在此处即为

MyInterceptor)绑定起来。

3.2.3.2 通知(advice)

Spring AOP的advice可以跨越多个被advice对象共享,或者每个被advice对象有

自己的advice。要实现advice,最简单的做法就是定义一个拦截器(Interceptor

)。它采用了AOP联盟(AOP Alliance)的通用AOP接口(接口定义为

aopalliance.jar)。要实现advice,需要实现aopalliance.jar中定义的

MethodInterceptor接口。

例如,我们定义了一个业务对象接口BusinessObject及其实现类

BusinessObjectImpl,该业务对象能够存储数据,其定义如下:
public interface BusinessObject
{
??? public void save();
}
public class BusinessObjectImpl implements BusinessObject
{
??? public void save()
??? {
???????? System.out.println(“saving domain object……”);
??? }
}

现在需要为业务对象BusinessObject的Save()方法,提供Lock机制。根据Spring

AOP的实现方式,我们可以定义一个LockInterceptor来实现MethodInterceptor接

口:
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class LockInterceptor implements MethodInterceptor
{
??? public Object invoke(MethodInvocation invocation) throws Throwable
??? {
??????? // TODO Auto-generated method stub
??????? lock();
??????? Object ret= invocation.proceed();
??????? unlock();
??????? return ret;
??? }
??? private void lock()
??? {
??????? System.out.println(“lock domain object…”);
??? }
??? private void unlock()
??? {
??????? System.out.println(“unlock domain object…”);
??? }
}

为将interceptor与具体的advice绑定起来,需要在配置文件中配置bean:
&lt;bean id=”MyInterceptor”

class=”test.aop.spring.LockInterceptor”/&gt;

3.2.3.3 AOP代理与IoC容器

由于Spring中提供了IoC容器(例如BeanFactory),因此我们可以通过Ioc机制,

利用ProxyFactoryBean来创建 AOP代理。ProxyFactoryBean和其他Spring的

FactoryBean实现一样,引入一个间接的层次。如果你定义一个名字为foo的

ProxyFactoryBean,引用foo的对象所看到的不是 ProxyFactoryBean实例本身,

而是由实现ProxyFactoryBean的类的 getObject()方法所创建的对象。这个方法

将创建一个包装了目标对象 的AOP代理。

AOP代理利用的是Java的动态代理技术,通过它就可以加载并执行AOP组件。同时

,还需要通过IoC的方式将advice注入到接口以及其实现类。以前面的业务对象

BusinessObject为例,在xml配置文件中的配置如下:
<bean id=”myAOPProxy”

class=”org.springframework.aop.framework.ProxyFactoryBean”>
??? <property name=”proxyInterfaces”>
?????? <value>test.aop.spring.BusinessObject</value>
??? </property>
??? <property name=”target”>
?????? <ref local=”impl” />
??? </property>
??? <property name=”interceptorNames”>
?????? <value>myPointcutAdvisor</value>
??? </property>
</bean>
<bean id=”impl”/>

通过上述对pointcut、advice、advisor和AOP代理的配置,我们就可以轻易地在

Spring中实现AOP,例如:
import org.springframework.context.ApplicationContext;
import

org.springframework.context.support.FileSystemXmlApplicationContext;

public class App
{
??? private BusinessObject bo = null;
??? public static void main(String[] args)
??? {
??????? ApplicationContext ctx=new FileSystemXmlApplicationContext

(“Bean.xml”);
??????? bo= (BusinessObject) ctx.getBean(“myAOPProxy”);
??????? bo.save();
??? }
}

首先,通过AOP代理获得BusinessObject对象。当调用BusinessObject对象的

save()方法时,拦截器 LockInterceptor根据RegexpMethodPointcutAdvisor配置

的pointcut和advice之间的关系,判定该方法的调用为join point,从而拦截该

方法调用,并注入advice的执行逻辑,即lock()和unlock(),最终实现了AOP。

3.2.3.4 引入(introduction)

在Spring AOP中,将introduction当作advice来处理。与一般的advice一样,

introduction advice相当于一种特殊类型的拦截通知,需要实现

IntroductionAdvisor和IntroductionInterceptor接口,而

IntroductionInterceptor接口继承自MethodInterceptor:
public interface IntroductionInterceptor extends MethodInterceptor
{
??? boolean implementsInterface(Class intf);
}

Introduction通知不能被用于任何pointcut,因为它只能作用于类层次上,而不

是方法。我们可以只用InterceptionIntroductionAdvisor来实现导入通知,它有

下面的方法:
public interface InterceptionIntroductionAdvisor extends

InterceptionAdvisor
{
??? ClassFilter getClassFilter();
??? IntroductionInterceptor getIntroductionInterceptor();
??? Class[] getInterfaces();
}

接下来,我以JBoss AOP一节中的例子来说明introduction在Spring AOP中的应用

。我们的目标仍然是为一个已有的业务对象引入第三方接口Tracing:
public interface Tracing
{
??? void enableTracing();
??? void disableTracing();
??? boolean enabled();
}

首先,我们需要一个做大量转化的IntroductionInterceptor。在这里,我们继承

org.springframework.aop.support.DelegatingIntroductionInterceptor 实现

类。当然我们可以直接实现IntroductionInterceptor接口,但是大多数情况下

DelegatingIntroductionInterceptor是最合适的。

DelegatingIntroductionInterceptor的设计是将introduction委托到真正实现

introduction 接口的接口,隐藏完成这些工作的拦截器。委托可以使用构造方法

参数设置到任何对象中;默认的委托就是自己(当无参数的构造方法被使用时)

。这样在下面的例子里,委托是DelegatingIntroductionInterceptor的子类

TracingMixin。给定一个委托(默认是自身)的

DelegatingIntroductionInterceptor实例寻找被这个委托(而不是

IntroductionInterceptor)实现的所有接口,并支持它们中任何一个导入。子类

如TracingMixi也可能调用suppressInterflace(Class intf) 方法来隐藏不应暴

露的接口。然而,不管IntroductionInterceptor 准备支持多少接口,

IntroductionAdvisor将控制哪个接口将被实际暴露。一个导入的接口将隐藏目标

的同一个接口的所有实现。

这样,TracingMixin继承DelegatingIntroductionInterceptor并自己实现接口

Tracing。父类自动选择支持introduction的Tracing,所以我们不需要指定它。

用这种方法我们可以导入任意数量的接口。
public class TracingMixin extends DelegatingIntroductionInterceptor

implements Tracing
{
??? private boolean enabled;
??? public void enableTracing ()
??? {
??????? this.enabled = true;
??? }

??? public void disableTracing ()
??? {
??????? this. enabled = false;
??? }

??? public boolean enabled()
??? {
??????? return this.enabled;
??? }
??? public Object invoke(MethodInvocation invocation) throws Throwable
??? {?????
??????? return super.invoke(invocation);
??? }
}

通常不要需要改写invoke()方法:实现DelegatingIntroductionInterceptor就足

够了,如果是引入的方法,DelegatingIntroductionInterceptor实现会调用委托

方法, 否则继续沿着连接点处理。

所需的introduction advisor是很简单的。只需保存一个独立的TracingMixin实

例,并指定导入的接口,在这里就是Tracing。此时,TracingMixin没有相关配置

,所以我们简单地使用new来创建它。

public class TracingMixinAdvisor extends DefaultIntroductionAdvisor
{
??? public TracingMixinAdvisor() {
??????? super(new TracingMixin(),Tracing.class);
??? }
}

我们可以非常简单地使用这个advisor。它不需要任何配置。(但是,有一点是必

要的:就是不可能在没有IntroductionAdvisor 的情况下使用

IntroductionInterceptor。) 和引入一样,通常 advisor必须是针对每个实例

的,并且是有状态的。我们会有不同的TracingMixinAdvisor。每个被通知对象,

会有不同的 TracingMixin。advisor组成了被通知对象的状态的一部分。

在Spring中,Spring AOP的核心API已经基本稳定了。和Spring的其它部分一样,

AOP框架是模块化的,在保留基础设计的同时提供扩展。在Spring 1.1到1.2阶段

有很多地方可能会有所提高,但是这些地方也保留了向后兼容性。它们是:

(一)性能的提高:AOP代理的创建由工厂通过策略接口处理。因此能够支持额外

的AOP 代理类型而不影响用户代码或核心实现。
(二)更具表达力的pointcut:Spring目前提供了一个具有表达力的切入点接口

,同时添加了更多的切入点实现。Spring正在考虑提供一个简单但具有强大表达

式语言的实现。

2010十月2

IoC和AOP

这两个概念基本上是一个设计层的概念,主要讲的就是怎么去分离关注,用面向

对象的话说,就是怎么把职责进行分离。而这两个模式,我个人认为都有一个共

同点,就是变以前的主动为被动,而我认为,这种改变可能也是将来面向对象发

展的一个趋势。

首先说说什么叫主动。写过面向对象程序的人都知道,面向对象与面向过程的区

别就是,面向对象是由一大堆对象组成的,对象通过协作完成面向过程中的任务

。假设现在有对象A和B,那么当A需要使用B中的方法时,那么在A内部,就会有有

一个对B方法的调用,这种调用就称为主动调用。代码大概会如下:

public class A{

B b;

public void methodA(){

b.methodB();

}

}

这里为了下文解释方便,我增加了一个调用点的定义,调用点就是调用发生的地

方。也就是上面

b.methodB()中的b。

理解了什么叫主动之后,我想就先介绍什么叫IoC。IoC的全称这里就不说了,他

的字面意思就是控制反转。在上面的代码当中,由于A调用了B的方法,因此就形

成了一个A对B的依赖,这本身并没有什么问题。但是OO的思想是希望我们基于接

口编程,而不是基于实现编程。因此,系统设计将不止是原有的 A,B,而需要变

成IA,IB,A,B,其中IA,IB是接口,A,B是对应的实现类,然后为了使得A中现

在对B的实现依赖变成对接口的依赖,代码应该变成这样。

public class A implements IA{

IB b;

public void methodA(){

b.methodB();

}

}

这里虽然我们是基于接口编程了,但大家知道,在这中间,我们需要有一个步骤

把b指向一个IB的实现类B,这个怎么做,就是IoC要做的事情,这里就不细说了。

但简单来说,没有IoC,我们可能需要在A中通过某种方法去获取一个B的实例,但

有了IoC,她就能在A不参与的情况下,给我们一个B的实例,所以,IoC要做的就

是在调用点上从原来的主动生成一个调用点,变成被动的接受一个调用点。

接着就是AOP,全称也不说了,字面意思就是面向方面编程。举一个最普遍的例子

,就是如果我们代码需要做日志的话,那么在没有AOP的时候,我们的代码可能就

是这样:

public class A{

public void methodA(){

do log;

b.methodB();

}

}

这里methodA()中的做日志并不是方法本身的逻辑功能,而是一个附属功能,因此

,我们需要把它分离出去。怎么分离,就是AOP要做的事情,简单来说,就是系统

在调用者不知情的情况下,为我们的类A增加了一个代理类,她把我们的类A包装

了起来,像这样:

public class AP extends A{

A a;

public void methodA(){

do log;

a.methodA():

}

}

public class A{

public void methodA(){

b.methodB();

}

}

于是,当我们以为自己在调用A的methodA()方法时,实际调用的将是AP中的

methodA(),于是就可以把做日志的功能从原有的 methodA()中分离了出去。所以

,AOP要做的就是在用户不知道的情况下,将我们的调用点包裹了起来,从而把原

来的功能进行了分离。

2010十月2

getHibernateTemple() 出现 NullPointerException!

Spring实践 评论关闭

原因:getHibernateTemple作用:在DAO类操作实体类时应用,因对数据库进行操作,故要获得在applicationContext.xml数据库的配置信息,如:当前实体类*.hbm.xml信息 但getHibernateTemple位于DAO中,不能自己获得此重要信息,要通过DAO来获得。
获得方式:DAO 继承HibernateDaoSupport类,在applicationContext中为此DAO配置sessionfactory属性
<bean id=”consultingDao”
parent=”dao”>
<property name=”sessionFactory” ref=”sessionFactory” />? //sessionFactory当指定Spring接管hibernate时自动配置
</bean>

2010十月2

手动测试DAO类运行

Spring实践 评论关闭

因DAO类要注入SessionFactory才能使得HibernateTemple运行,故要手动获得配置文件,用配置文件中的DAO来完成对象的建立,而不
是用new来创建DAO类来进行数据库的操作。

String [] confile = {
??????? “WebRoot\\WEB-INF\\applicationContext-db.xml”,
??????? “WebRoot\\WEB-INF\\applicationContext-dao.xml”,
??????? “WebRoot\\WEB-INF\\applicationContext-service.xml”
};
ApplicationContext ac = new FileSystemXmlApplicationContext(confile );
ManageDAOInf mi = (ManageDAOInf) ac.getBean( “manageInf” );

2010十月2

ApplicationContext路径问题

Spring实践 评论关闭

两种创建方法:
1,ClassPathXmlApplicationContext

ApplicationContext ac = new ClassPathXmlApplicationContext(“applicationContext.xml”);

(1)默认路径:ClassPathXmlApplicationContext 既然名为ClassPath,那么它的相对路径就是ClassPath,即:src/
故用applicationContext.xml找的就是src下的”applicationContext.xml文件!!!
(2)绝对路径:前加前缀:file:
??? ApplicationContext ac = new ClassPathXmlApplicationContext( “file:E:\\workspace\\lj\\WebRoot\\WEB-INF\\applicationContext-db.xml” )

2,FileSystemXmlApplicationContext
ApplicationContext ac = new FileSystemXmlApplicationContext(“applicationContext.xml”);
默认路径:若写相对路径,相对的是工程根目录。即:lj/applicationContext.xml, 此xml文件与src文件夹平行。
? 可直接写绝对路径,加不加file都可以。

几种前缀:file:指定绝对路径?????????? ClassPath:指定src/路径?? (1默认,2要加才可)

注:(1)在类中进行手动注入时,注意的是路径要参考源工程的目录结构,而不是发布后的目录结果。
(2)读取多个配置文件:
? String [] confile = {
??????? “WebRoot\\WEB-INF\\applicationContext-db.xml”,
??????? “WebRoot\\WEB-INF\\applicationContext-dao.xml”,
??????? “WebRoot\\WEB-INF\\applicationContext-service.xml”
};
ApplicationContext ac = new FileSystemXmlApplicationContext(confile );

2010十月2

Spring与普通使用的融合 –编码测试

方式:在类中手动连接:
?? ? ?? ApplicationContext ac = new ClassPathXmlApplicationContext(“applicationContext.xml”);
??? ??? ManageInf mi = (ManageInf) ac.getBean( “manageInf” );
??? ??? mi.update();
这样一与配置文件相接触,IOC, AOP之类就会自动完成注入与关联!
而与Struts整合因在web.xml中配置了listener,故一切都是自动完成,无需手动创建bean.

2010十月2

Spring与 Struts 整合

Spring实践 评论关闭

1, Spring 在web.xml中配置Spring listener
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>
2, Strutx 配置
1.x, 在struts-config.xml中为action的type指定为 org.springframework.web.struts.DelegatingActionProxy
2.x? 在struts.xml中为action的class指定为具体类(只注入属性),或bean id
3, Spring在 applicationContext.xml中配置bean id
1.x 全部配置,bean id与action的path相同
2.0? 按action的class做相应配置,
???? 若是属性注入, bean id 要与action类中的属性名相同
???? 若是全部注入, bean id 要与action在配置文件中中指定的class相同

2010十月2

Spring与Struts1.x的整合

Spring实践 评论关闭

1,添加struts1.x, Spring能力

2, 在struts1.x的配置文件struts-config.xml中配置与Spring的联系
<action-mappings >
<action
attribute=”loginForm”
input=”/login.jsp”
name=”loginForm”
path=”/login”?? //在Spring的applicationContext.xml中要用此path当做bean id
scope=”request”
type=”org.springframework.web.struts.DelegatingActionProxy” >
?? //交由Spring来生成action,而不是在此就指定具体的类
<forward name=”success” path=”/success.jsp” />
</action>
</action-mappings>

<message-resources parameter=”com.yourcompany.struts.ApplicationResources” />
<!– 集成Spring插件 –>
<plug-in className=”org.springframework.web.struts.ContextLoaderPlugIn”>
<set-property property=”contextConfigLocation” value=”/WEB-INF/classes/applicationContext.xml”/>
</plug-in>
? // struts添加Spring插件
注:也可不用插件, 利用如struts 2.0 的方式在web.xml中配置Spring监听器 即:
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>

3,在Spring中添加action的生成
<bean name=”/login” scope=”prototype” >
<property name=”myService”>
??? <ref bean=”myService”/>
</property>
</bean>

ps: struts 1.x , struts2.0与Spring整合的区别:
(1)1.x 是整个action注入,生成由Spring负责,而2.0让spring负责属性的注入,也可负责action的创建。
(2)1.x与Spring的联系是在其配置文件struts-config.xml中通过插件机制完成,也可在web.xml中配置Spring过滤器完成.都市而2.0是在 web.xml中通过配置过滤器来完成这种联系。
(3)?? 1.x 是全部注入:struts-config.xml中要配置每个action与spring的联系???????????? type=”org.springframework.web.struts.DelegatingActionProxy” >
然后在spring的applicationContext.xml中配置对应的bean
??? 2.0不仅有全部注入,还有属性注入.
???? 2.0 属性注入,在struts2.0的struts.xml中无须配置每个action与Spring的联系,只须在action类中指定一个属性名,此属性名与application.context.xml中某一bean id相同即可。
???? 2.0 所有注入:托管action的所有生命周期,要在struts.xml中为action的class指定为Spring的applicationContext.xml中的一个bean id,这样就可完成所有托管.
无论是1.x,还是2.0,若想让spring注入属性,必须在类中为此属性指定set,get方法,而不论此属性是private,还是public

2010十月2

Spring与Hibernate的融合

Spring实践 评论关闭

1,? 利用myeclipse,会少中一个jar包,需要手动加入 commons-pool-1.3.jar
http://mirrors.ibiblio.org/pub/mirrors/maven2/commons-pool/commons-pool/1.3/commons-pool-1.3.jar
或查找myeclipse安装目录, 在如下位置
myeclipse\eclipse\plugins\com.genuitec.org.hibernate.eclipse_6.0.1.zmyeclipse601200710\lib\springhibernate

2, 添加Spring后加hibernate时,hibernate最好都选中所有类库,之后选择Spring的applicationContext.xml,
这样就会用getHibernateTemplate().save(transientInstance)之类代替session进行托管,这是Spring与Hibernate整合的最大好处。
hibernate 的hbm.xml文件要在applicationContext.xml中引入:即
<bean id=”sessionFactory”
class=”org.springframework.orm.hibernate3.LocalSessionFactoryBean”>

<property name=”mappingResources”>
??? <list>
??????? <value>com/lvjian/model/News.hbm.xml</value>??????
??? </list>
</bean>

对DAO注入:sessionFactory
<bean id=”consultingDao”
parent=”dao”>
<property name=”sessionFactory” ref=”sessionFactory” />?
????????? //sessionFactory当指定Spring接管hibernate时自动配置, DAO类要实现HibernateSurrort类
</bean>

3, 在应用中,最好对生成的dao进行包装,用一个接口来定义dao方法,在action中利用这些接口提供的方法进行操作
而在applicationContext.xml 对接口id注入impl类!
即:在表层上只留接口,实现由applicationContext.xml配置完成
方法主要可以有:
???????????? 1, 查询? getAdmin(id) ,getAdmins 得到所有, findByProperty(String propertyName, Object value)
???????????? 2, 插入 insertAdmin(Admin obj)
???????????? 3,更新? updateAdmin(Admin obj)
???????????? 4 删除?? deleteAdmin(Integer obj_id)

注:DAO类要实现HibernateSurrort类
com.yourcompany.dao.inf
com.yourcompany.dao.impl

2010十月2

SSH中Spring要选的能力

Spring实践 评论关闭

String 2.0 Core Libraries
String 2.0 Persistence JDBC Libraries
String 2.0 Web Libraries