add TransactionContextBuilder based on Spring AOP

This commit is contained in:
Kelven Yang 2012-10-25 15:01:12 -07:00
parent ad3e98c1eb
commit c272cf6b69
6 changed files with 188 additions and 0 deletions

15
pom.xml
View File

@ -251,6 +251,21 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,61 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.utils.db;
import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
public class TransactionContextBuilder {
public TransactionContextBuilder() {
}
public Object AroundAnyMethod(ProceedingJoinPoint call) throws Throwable {
MethodSignature methodSignature = (MethodSignature)call.getSignature();
Method targetMethod = methodSignature.getMethod();
if(needToIntercept(targetMethod)) {
Transaction txn = Transaction.open(call.getSignature().getName());
Object ret = null;
try {
ret = call.proceed();
} finally {
txn.close();
}
return ret;
}
return call.proceed();
}
private boolean needToIntercept(Method method) {
DB db = method.getAnnotation(DB.class);
if (db != null) {
return db.txn();
}
Class<?> clazz = method.getDeclaringClass();
do {
db = clazz.getAnnotation(DB.class);
if (db != null) {
return db.txn();
}
clazz = clazz.getSuperclass();
} while (clazz != Object.class && clazz != null);
return false;
}
}

View File

@ -0,0 +1,30 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.utils.db;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@Component
@DB
public class DbAnnotatedBase {
private static final Logger s_logger = Logger.getLogger(DbAnnotatedBase.class);
public void MethodWithClassDbAnnotated() {
s_logger.info("called");
}
}

View File

@ -0,0 +1,27 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.utils.db;
import org.springframework.stereotype.Component;
@Component
public class DbAnnotatedBaseDerived {
@DB
public void DbAnnotatedMethod() {
}
}

View File

@ -0,0 +1,25 @@
package com.cloud.utils.db;
import javax.inject.Inject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:/transactioncontextBuilderTest.xml")
public class TransactionContextBuilderTest {
@Inject
DbAnnotatedBaseDerived _derived;
@Inject
DbAnnotatedBase _base;
@Test
public void test() {
_derived.DbAnnotatedMethod();
_base.MethodWithClassDbAnnotated();
}
}

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="org.apache.cloudstack, com.cloud" />
<aop:config proxy-target-class="true">
<aop:aspect id="dbContextBuilder" ref="transactionContextBuilder">
<aop:pointcut id="captureAnyMethod"
expression="execution(* *(..))" />
<aop:around pointcut-ref="captureAnyMethod" method="AroundAnyMethod"/>
</aop:aspect>
</aop:config>
<bean id="transactionContextBuilder" class="com.cloud.utils.db.TransactionContextBuilder" />
</beans>