随笔 - 8, 文章 - 0, 评论 - 4, 引用 - 0
数据加载中……

2009年2月10日

Java静态代理和动态代理

网上和bolg上相关例子不少,今天自己动手写了个例子作为学习笔记。
首先java代理分为静态代理和动态代理,动态代理中java提供的动态代理需要动态代理一个inteface,如果没有inteface则需要使用实现cglib提供的接口。
下面例子只实现动态代理
public class MyProxy implements InvocationHandler{
    
    
static Object proxyObj = null;    
    
    
public static Object getInstance(Object obj){
        proxyObj
= obj;
        
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new MyProxy());
    }

    
    
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(
"使用代理..");
        
return method.invoke(proxyObj, args);
    }

}

实现方式
public static void main(String[] args) {
        ILeaveService service 
= (ILeaveService)MyProxy.getInstance(new LeaveServiceImpl());
        
try {
            service.listBizObjByHql(
"");
        }

        
catch (ServiceException e) {
            e.printStackTrace();
        }

    }

打印出:
使用代理..
query Hql..
使用Cglib
public class Test2 implements MethodInterceptor {
        
    
    
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println(
"cglib proxy");
        
return methodProxy.invokeSuper(obj, args);
    }

    
}

实现
public static void main(String[] args) {
        Enhancer enhancer 
= new  Enhancer();
        enhancer.setSuperclass(Test3.class);
        enhancer.setCallback(new Test2());        

        Test3 test 
= (Test3)enhancer.create();
        test.prinInfo(
"p.");
    }
输出
cglib proxy
p.
过滤器
public class Test4 implements CallbackFilter{

    
public int accept(Method method) {
        
if(method.getName().equals("method1")){
            
return 1;
        }
else if(method.getName().equals("method2")){
            
return 0;
        }

        
return 0;
    }

    
}
只有返回0的才执行(cglib中的NoOp.INSTANCE就是一个空的拦截器
    public static void main(String[] args) {        
        Callback [] callbacks 
= new Callback[]{new Test2(),NoOp.INSTANCE};
        Enhancer enhancer 
= new Enhancer();
        enhancer.setSuperclass(Test3.
class);
        enhancer.setCallbacks(callbacks);
        enhancer.setCallbackFilter(
new Test4());
        Test3 test3 
= (Test3)enhancer.create();
        test3.method1();
        test3.method2();
    }

    
}

执行结果
method1
cglib proxy
method2

posted @ 2009-02-18 16:52 Pitey 阅读(471) | 评论 (0)编辑 收藏

转:Message Driven POJO

作者:江南白衣 
  
    一直希望那些J字头的协议能有几个提前告老还乡的,好减轻一下我们的负担,特别是这WebService满天飞的时代。但似乎还有很久都轮不到JMS的消失:

    1.因为
    1.它是《Effective Enterprise Java》的一个实践。 
    可以把不影响用户执行结果又比较耗时的任务(比如发邮件通知管理员)异步的扔给JMS 服务端去做,而尽快的把屏幕返还给用户。
    而且服务端能够多线程排队响应--高并发的请求。

    2. 可以在Java世界里达到最高的解耦。
       对比WebService,JMS的客户端与服务端无需直连,甚至无需知晓对方是谁、在哪里、有多少人,只要对流过的信息作响应就行了。对牵一发动全身的企业应用来说很轻省。
       
     2. 但是
     1. Message Bean带着EJB系的荣光,步骤比较繁杂,你需要实现MessageDrivenBean、MessageListener接口,还需要设置EJB的配置信息,然后是deploy....

     2. Spring 1.x 提供的JMS Template简化了JMS Client端的编程,但并没有涉及到服务端的改造。

     3. 所以,SpringSide的Message Driven POJO方案

      Spring JMS Template + ActiveMQ + Jencks

1. 它是Lightweight的,基本上只是普通POJO,不用搞太多东西。

2. 它是Spring Base的,可以使用Spring的各种特性如IOC、AOP。

3. 它是Effective的,基于Jencks的JCA Container实现 pool connection,control transactions and manage security。

4. 但它是withdout EJB Container的。

其实它还不是100% POJO,除非再用上Lingo,但我已不想走得太远。

4.黄金版配置
      如果你想找一个ActiveMQ 3.2 Stable版+Spring的100%可行的配置文件,估计只能到SpringSide项目里看了。网上的文章,不是已过时,就是不切题。

     推荐中英两份最接近的文档:
     捷特慈朋(IDEA中国): Spring和Message Bean的整合
     Spring loaded:  Message-Driven POJOs 

     不过它们都有个outdate的地方--ActiveMQ3.2开始不再自带JCA Cotainer了,而是将其与Gernimo 合作而成了Jencks,需另外安装。

 5.SpringSide旅游指南

      pom.xml里的JMS部分 --所需的依赖包。
      applicationContext-jms.xml --黄金版配置文件。
      activemq.xml  --AcitveMQ Broker配置文件。
      OrderPlaceMDP.java --Message Driven Pojo。
      JmsTest.java --单元测试用例。
      OrderManger.java的NodifyOrder()函数 --实际应用的地方。 

 POJO太简单,唯一麻烦的配置文件已注释,这里也就无话了。

posted @ 2009-02-11 09:52 Pitey 阅读(237) | 评论 (0)编辑 收藏

[导入]一次Java垃圾收集调优实战

     摘要: GC调优是个很实验很伽利略的活儿,最后服务的处理速度从1180 tps 上升到1380 tps,调整两个参数提升17%的性能还是笔很划算的买卖.....  阅读全文

江南白衣 2008-07-09 10:13 发表评论

文章来源:http://www.blogjava.net/calvin/archive/2008/07/09/213535.html

posted @ 2009-02-11 09:17 Pitey 阅读(149) | 评论 (0)编辑 收藏

Spring事物拦截器学习笔记

Spring事物拦截器,按照通知方式分为[前置通知(Before advice),返回后通知(After returning advice)
,抛出后通知(After throwing advice),后通知(After (finally) advice),环绕通知(Around Advice)]
配置方式分@AspectJ,XML,网上比较多的是Spring1.1或xml+@AspectJ方式配置,例子使用XML方式配置

1.定义切面类接口,切面类实现这个接口。声明(如果被代理的目标对象实现了至少一个接口,则会使用JDK动态代理。所有该目标类型实现的接口都将被代理。若该目标对象没有实现任何接口,则创建一个CGLIB代理)

public interface ITestAdvice {
 
 
public void doPlay();
 
 
public void doStop(Object reval);

}



public class Tv implements ITestAdvice{
 
 
 
public void doStop(Object reval) {
  System.out.println(reval.toString() 
+ "关闭电视机!");
 }

 
 
public void doPlay() {
  System.out.println(
"打开电视机!");
 }

 
}


 

2.定义前置通知拦截处理类

 

public class TestMethodBeforeAdvice  {
 
 
public void before(JoinPoint jpt) {  //参数JoinPoint为默认参数
  System.out.println(
"正在打开电视..");
 }

 
}



3.定义拦截器配置文件

<bean id="tv" class="com.pitey.demo.Tv" />
<bean id="beforeAdvice" class="com.pitey.demo.TestMethodBeforeAdvice" />
 
 
<aop:aspectj-autoproxy proxy-target-class="true"/>
 
<aop:config>
  
<!-- 定义切入点 -->
  
<aop:pointcut id="methodAdvice" expression="execution(* com.pitey.demo.*.*(..))" />
  
<!-- 定义切面 -->
  
<aop:aspect id="beforeAdviceAspect" ref="beforeAdvice">
   
<!-- 定义前置通知 -->   
   
<aop:before method="before" pointcut-ref="methodAdvice"/>    
 
</aop:config>


4.测试一下前置通知

public static void main(String[] args) {
        ApplicationContext context 
= new ClassPathXmlApplicationContext("config\\advice.xml");
        Tv tv 
= (Tv)context.getBean("tv");
        tv.doPlay();        
    }


结果:
            正在打开电视机..
            打开电视机


5.定义返回后通知拦截处理类

public class TestAfterReturnAdvice {
 
 
public void afterReturning(Object retVal) throws Throwable {
  String returnVal 
= 电视机已经打开!";
  System.out.println(returnVal);
  retVal
= (Object)returnVal;
 }

 
}



6.定义拦截器配置文件

 

<bean id="afterReturnAdvice" class="com.pitey.demo.TestAfterReturnAdvice"/>
 
<aop:config>
  
<!-- 定义切面 -->
  
<aop:aspect id="afterReturnAdviceAspect" ref="afterReturnAdvice">
   
<!-- 定义后置返回通知  -->   
   
<aop:after-returning method="afterReturning" pointcut-ref="methodAdvice" returning="retVal"/> //returing 为返回参数
 </aop:config>


7.测试一下返回后通知

public static void main(String[] args) {
        ApplicationContext context 
= new ClassPathXmlApplicationContext("config\\advice.xml");
        Tv tv 
= (Tv)context.getBean("tv");
        tv.doPlay();        
    }


结果:
            正在打开电视机..
            打开电视机
            电视机已经打开
!


8.定义环绕通知拦截处理类(环绕通知在一个方法执行之前和之后执行。 它使得通知有机会既在一个方法执行之前又在执行之后运行。并且,它可以决定这个方法在什么时候执行,如何执行,甚至是否执行。 环绕通知经常在在某线程安全的环境下,你需要在一个方法执行之前和之后共享某种状态的时候使用。 请尽量使用最简单的满足你需求的通知。(比如如果前置通知(before advice)也可以适用的情况下不要使用环绕通知))
通知方法的第一个参数的类型必须是 ProceedingJoinPoint 类型。在通知的主体中,调用 ProceedingJoinPointproceed() 方法来执行真正的方法。 proceed 方法也可能会被调用并且传入一个 Object[] 对象 - 该数组将作为方法执行时候的参数。

public class TestMethodIntercepor{
 
 
public Object doBasicProfiling(ProceedingJoinPoint  pjp) throws Throwable {
  System.out.println(
"begining");
  Object obj 
= pjp.proceed();
  
  System.out.println(
"ending..");
  
return obj;
 }
 
}




9.定义拦截器配置文件

 

<bean id="aroundAdvice" class="com.pitey.demo.TestMethodIntercepor"/>
 
<aop:config>
  
<!-- 定义切面 -->
  
<aop:aspect id="aroundAspect" ref="aroundAdvice">
 
<aop:around method="doBasicProfiling" pointcut-ref="methodBeforeAdvice"/>
  
</aop:aspect>
 
</aop:config>



10.测试一下环绕通知

public static void main(String[] args) {
        ApplicationContext context 
= new ClassPathXmlApplicationContext("config\\advice.xml");
        Tv tv 
= (Tv)context.getBean("tv");
        tv.doPlay();        
    }


结果:
            begining
            打开电视机
            ending..

posted @ 2009-02-10 23:07 Pitey 阅读(1669) | 评论 (0)编辑 收藏