yuyee

#

使用Annotation来完成spring aop

spring AOP中,可以通过annotation来简化XML上的配置,可以很灵活的使切面切入到自己想要的方法上,而不需要象aop:config里一定要切入到特定命名方法上
使用annotation来表示pointcut,需要在xml里配置org.springframework.aop.support.annotation.AnnotationMatchingPointcut,
如:<bean name="timeoutPointcut"
class="org.springframework.aop.support.annotation.AnnotationMatchingPointcut">
<constructor-arg index="0"
value="com.hengtian.fxfundsystem.aop.annotation.UseAOPAnnotation">
</constructor-arg>
<constructor-arg index="1"
value="com.hengtian.fxfundsystem.aop.annotation.TimeoutAnnotation" />
</bean>
第一个参数是标在目标类上的annotation,第二天参数是标注在方法上的Annotation
因此,首先要在自己的工程里定义2个annotation,一个为TimeoutAnnotation,一个为UseAOPAnnotation
@Target({ElementType.TYPE })//表示类标注
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface UseAOPAnnotation {

}
@Target({ElementType.METHOD})//表示方法标注
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeoutAnnotation {
/**
* 默认值(-1):表示不启用超时
*/
public static final long DefaultValue = -1;

/**
* 超时时间,单位是ms
* @return
*/
long value() default DefaultValue;

}
在需要AOP的类上使用
@UseAOPAnnotation
@Component("StrongDuck")  
public class StrongDuck {
@TimeoutAnnotation(70000)
public void say(){
System.out.println("I am a strong duck");
}
}
timeout通知:
public class TimeoutAdvice implements MethodInterceptor {

/*
* (non-Javadoc)
* @see
* org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept
* .MethodInvocation)
*/
public Object invoke(final MethodInvocation methodInvocation)
throws Throwable {

Method targetMethod = methodInvocation.getMethod();
TimeoutAnnotation timeoutAnnotation = targetMethod
.getAnnotation(TimeoutAnnotation.class);
if (timeoutAnnotation != null) {
long waitTime = timeoutAnnotation.value();
if (waitTime != TimeoutAnnotation.DefaultValue) {
Future<?> task = ThreadManager.ExecutorService
.submit(encapsulateSyncToAsync(methodInvocation));
return getAsyncResult(waitTime, task);
}

}
return methodInvocation.proceed();
}
XML中配置拦截器:
<bean id="timeoutInterceptor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="timeoutAdvice" />
<property name="pointcut" ref="timeoutPointcut" />
</bean>
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<property name="proxyTargetClass"><!-- 基于类的代理 -->
<value>true</value>
</property>
</bean>
这样,spring就会为你生成aop代理类实现AOP


posted @ 2010-10-25 16:52 羔羊| 编辑 收藏

oracle中的递归查询

start with .... connect by prior.....,如果prior缺省,则只能查询符合条件的起始行,并不能递归
从root到末梢:select * from permissiontable t start with parentid=1 connect by prior id=parentid
从末梢到root:select * from permissiontable t start with id=32 connect by prior parentid=id

posted @ 2010-10-25 15:55 羔羊| 编辑 收藏

oracle分组取值

oracle中有rownum伪列,select rownum from t where rownum<3;表示取整个结果集的前2条记录
当时如果要取分组后每个组里的前几条记录,则rownum无法实现,必须使用oracle里的分析函数,比如row_number()over(partition by 分组字段 order by 排序字段),实现分组后编号

select s.*
  from (select row_number() over(partition by p.trader order by p.branch)  rn,p.*
               
          from spotdeal p) s
 where s.rn < 3

posted @ 2010-10-25 15:39 羔羊| 编辑 收藏

JMM小记

JMM,顾名思义,java memory model。他有3个特征:原子性,可见性,有序性。
JVM系统中都有个一主存,JAVA中所有变量都是存储在主存中,对所有线程都是共享的。
而每条线程都有自己的工作内存,工作内存中保存的是主存中某些变量的值,线程对所有变量的修改都是在工作内存中进行,线程之间无法直接互相访问,变量的传递都是通过主存完成。
可见性:JMM中并发线程修改变量,必须将工作内存中的变量同步到主存后,其他线程才能访问到
有续性:通过JAVA提供的同步机制或者volatile关键字 来保证内存的有序性
JAVA中保证多核系统JMM缓存一致性原则:happens-before ordering(先行发生排序)
JAVA提供了
1.synchronized关键字
2.volatile关键字
3.final关键字
4.同步包中的locks
5.同步包中的原子类

posted @ 2010-10-25 15:04 羔羊| 编辑 收藏

hibernate简单知识

Session接口几个基本操作 

    • 1.get()方法:先确认该ID对应的数据是否存在,先经过session缓存,再二级缓存,之后是数据库,如果不存在,返回null
    • 2.load()方法:hibernate会默认你是存在的,他会放心的使用代理类在延迟加载数据,当用到他的其他属性时,就会跑去数据库中查询,如果不在,抛异常
    • 3.list()方法:去数据库读取数据,填充缓存,
    • 4.iterator()方法:先去数据库select id from table,之后到缓存中查找,如果不存在,出现N+1问题.

缓存 

    • 1.一级缓存:session级缓存,如果session关闭,,清空,释放内存
 
    • 2.二级缓存:SessionFactory级别的全局缓存,它底下可以使用不同的缓存类库,比如ehcache、oscache等,需要设置hibernate.cache.provider_class
    • 缓存可以看成是个hastable,典型的空间换时间,一般在读写比高的情况下使用

Hibernate中使用二级缓存 

    • Class的缓存  
      对于一条记录,也就是一个PO来说,是根据ID来找的,缓存的key就是ID,value是POJO。无论list,load还是iterate,只要读出一个对象,都会填充缓存。但是list不会使用缓存,而iterate会先取数据库select id出来,然后一个id一个id的load,如果在缓存里面有,就从缓存取,没有的话就去数据库load。假设是读写缓存,需要设置:  
      <cache usage=“read-write”/><缓存并发策略>
    • 使用二级缓存第三方插件ehcache.jar来实现,在hibernate.cfg.xml中配置
    • 如下图:是我测试TestDAO工程的hiberante.cfg.xml配置

Hiberante.cfg.xml

ehcache.xml配置 

    • <defaultCache  
              maxElementsInMemory=“10000” //在缓存区最大元素 默认为10000;  
              eternal=“false”  //是否永久不超时  
              timeToIdleSeconds=“120”  // :缓存数据的钝化时间,也就是在一个元素消亡之前,两次访问时间的最大时间间隔值  
              timeToLiveSeconds=“120” //从创建后存活的最长时间  
              overflowToDisk="true" //溢出到硬盘;  
              /> 
 
    • 每个存储的CLASS都要有这样的配置,如果你没配置,Hibernate会警告你,然后使用缺省的defaultCache

查询缓存  

    • 需要配置<property name="hibernate.cache.use_query_cache">true</property>
    • query.setCacheable(true);//激活查询缓存  
      query.setCacheRegion(“myCacheRegion”);//指定要使用的cacheRegion,如果不做,会使用标准的查询缓存的配置
    • 查询缓存来说,缓存的key是根据hql生成的sql,再加上参数,分页等信息
    • 重点:如果是list()方式的话,value在这里并不是整个结果集,而是查询出来的一串ID.
    • 不管是list方法还是iterate方法,第一次查询的时候,它们的查询方式和它们平时的方式是一样的,list执行一条sql,iterate执行1+N条,多出来的行为是它们填充了缓存。但是到同样条件第二次查询的时候,就都和iterate的行为一样了,根据缓存的key去缓存里面查到了value,value是一串id,然后在到class的缓存里面去一个一个的load出来。
    • 所以说,查询缓存需要打开相关类的class缓存。list和iterate方法第一次执行的时候,都是既填充查询缓存又填充class缓存的,还有一点,Class缓存的时间一定要比查询缓存长,不然还是会出现N+1问题

缓存与数据库同步 

    • hibernate在一个地方维护每个表的最后更新时间,其实也就是放在上面org.hibernate.cache. UpdateTimestampsCache所指定的缓存配置里面。 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
    •   
      当通过hibernate更新的时候,hibernate会知道这次更新影响了哪些表。然后它更新这些表的最后更新时间。每个缓存都有一个生成时间和这个缓存所查询的表,当hibernate查询一个缓存是否存在的时候,如果缓存存在,它还要取出缓存的生成时间和这个缓存所查询的表,然后去查找这些表的最后更新时间,如果有一个表在生成时间后更新过了,那么这个缓存是无效的。  
      可以看出,只要更新过一个表,那么凡是涉及到这个表的查询缓存就失效了,因此查询缓存的命中率可能会比较低。

使用二级缓存的前置条件 

    • 使用hiberante的应用对数据库具有独占访问权,既不能被第三方修改数据,因为那样缓存不知道你修改了数据,无法与数据库同步.
    • 如果自己程序里使用了JDBC来更新,不通过hiberante更新,也会出现跟数据库不同步的情况

posted @ 2010-10-25 00:30 羔羊| 编辑 收藏

JDK代理

JDK代理以前性能不怎么样,但1.6版本却有很大提升
/**
 * 行为接口
 * 
 * @author Administrator
 * 
 */
public interface Study {
public void doStudy();
}
/**
 * 目标对象
 * 
 * @author Administrator
 * 
 */
public class StudyImpl implements Study {

@Override
public void doStudy() {
System.out.println("study jdk proxy");
}

}


/**
 * 代理类
 * @author Administrator
 *
 */
public class JDKProxy implements InvocationHandler {

private Study s;

public JDKProxy(Study s) {
this.s = s;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before jdkproxy");
method.invoke(s, args);
System.out.println("after jdkproxy");
return null;
}
}

应用中进行调用:
public class Test {
public static void main(String[] args) throws SecurityException,
NoSuchMethodException, IllegalArgumentException,
InstantiationException, IllegalAccessException,
InvocationTargetException {
Class clazz = StudyImpl.class;//获取目标类的Class对象
Study st = new StudyImpl();//实例化一个目标类
Class proxClass = Proxy.getProxyClass(clazz.getClassLoader(), clazz
.getInterfaces());//通过Proxy静态方法,获取一个于目标类实现同样接口的Class对象,也可以说是兄弟类
Constructor c = proxClass
.getConstructor(new Class[] { InvocationHandler.class });//给这个类一个指定的公开的构造方法
Study ds = (Study) c.newInstance(new Object[] { new JDKProxy(st) });//实例化一个代理类
}
}

posted @ 2010-10-25 00:20 羔羊| 编辑 收藏

AOP日记


  最近在学着总结,因为常感觉做完东西,长久不用,过段时间就忘,下次想复习下都不行。
 AOP,面向方面编程,我们系统中有很多组件组成,每一个组件负责一部分业务功能,
 但是这些组件往往又带有一部分核心功能外的附加功能,而且是重复代码,如:日志,安全,事务! 通过AOP,实现这些附加功能的可重复利用。
 
 AOP其实可以看作是代理模式的扩展,写一个简单的代理
 
public class ProxySubject implements ProxyInterface {
private Subject innerObj;// 真正的对象

@Override
public void handle() {
innerObj = new Subject();
// 做额外的事情
innerObj.handle();// 真正的处理业务
// 做额外的事情
}
}

 Aop中叫代理类为advice,可以有多个连接起来,一个事件链

  实现AOP,还需要涉及到JAVA的反射,通过反射,获取method对象,并执行方法,AOP规范包里有个接口

 

 

public interface MethodInterceptor extends Interceptor {

    

     *Implement this method to perform extra treatments before and

     * after the invocation. Polite implementations would certainly

     * like to invoke {@link Joinpoint#proceed()}.

     *

     * @param invocation the method invocation joinpoint

     * @return the result of the call to {@link

     * Joinpoint#proceed()}, might be intercepted by the

     * interceptor.

     *

     * @throws Throwable if the interceptors or the

     * target-object throws an exception.  

     Object invoke(MethodInvocation invocation) throws Throwable;

      }

      通过 MethodInvocation的 getMethod()获得方法对象,并执行

      这样,如果你一个类中有很多方法,就可以通过这么一个

      

      AOP中生成代理类有3种方式,

      1.静态编译时期,源代码生成,为每个符合条件的类生成一个代理类

      2.静态字节码增强通过ASM/CGLIB分析字节码,生成代理类

      3.动态字节码增强,spring aop就是这样,ASM/CGLIB或者JDK的动态代理

      AOP的原理可以理解为代理模式+放射+自动字节码生成

Spring中动态代理有2种方式,一种是通过CGLIB,一种是JDK。

什么时候采用JDK什么时候采用CGLIB动态生成,主要取决于你又没实现接口,JDK动态代理需要目标类实现某接口,而CGLIB则是生成目标类的子类

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {

if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {

Class targetClass = config.getTargetClass();

if (targetClass == null) {

throw new AopConfigException("TargetSource cannot determine target class: " +

"Either an interface or a target is required for proxy creation.");

}

if (targetClass.isInterface()) {

return new JdkDynamicAopProxy(config);

}

if (!cglibAvailable) {

throw new AopConfigException(

"Cannot proxy target class because CGLIB2 is not available. " +

"Add CGLIB to the class path or specify proxy interfaces.");

}

return CglibProxyFactory.createCglibProxy(config);

}

else {

return new JdkDynamicAopProxy(config);

}

}

这个是DefaultAopProxyFactory里创建代理类的方法


 

 

posted @ 2010-10-24 23:48 羔羊| 编辑 收藏

一些JDK自带的分析工具

jps:查看JAVA线程ID 
jinof: 
jinfo -flag MaxPermSize <PID>  查看VM参数信息
jstat; 
jstat -opt <PID> 一般常用-gcutil查看垃圾收集信息,后面还可加一个间隔时间 
jmap: 
dump的生成工具,生成堆转储文件后可用MAT分析 jmap -dump:format=b,file=XX <pid> 
也可用jmap -histo <PID>将信息输出到控制台 
jconsole: 
jconsol是jdk自带的一个内存分析工具,它提供了图形界面。可以查看到被监控的jvm的内存信息,线程信息,类加载信息,MBean信息
jdk1.6提供了java visualVM,功能很全,类似Jprofiler
-XX:+HeapDumpOnOutOfMemoryError:这个参数指定在OOM时产生DUMP
-XX:HeapDumpPath 这个是要保存的 dump文件的路径,后缀为.hprof
例子:-XX:HeapDumpPath=C:\Documents and Settings\aoxianglin\Application Data\.visualvm\6u18\var\log\heapdump.hprof

posted @ 2010-09-26 11:29 羔羊| 编辑 收藏

仅列出标题
共2页: 上一页 1 2