Tuesday, December 12, 2006

Personal c++ tips(1) :_)

1. Operator overloading must have user’s self-definition argument.

2. void * can be evaluated by any point-type data except point to function.

3. void f(int i) and void f(const int i) can’t be declared at the same time. They are not overloaded functions. It products a compiled error. But if we add “const” or “volatile” to point or reference type argument, the compiler will look on these functions as two different functions.

4. Static data type can be declared as its affiliated class’s type in class body. But non-static data type can be only declared as its affiliated class’s point or reference in class body. See the following example:

class Bar {

public:

static Bar mem1; // ok

Bar* mem2; //ok

Bar mem3; //error

};

5. Arbitrary function point can be converted to void(*)() type by reinterpret_cast<>. And arbitrary functor point can be converted to void* type by static_cast<>

6. Any functions that don’t modify member field should be declared as const function. But if you wanna modify member field in const function. How to do it? Here lists two methods:

a. In class Y has a method like “void Y::f() const”. We can do some modifies in function body: void Y::f() const { ((Y*)this)->j++; } we convert this point to Y* compulsorily.

b. Using “mutable” keyword. mutable int j;

7. If a class type wants to be put into an union, it should meet demands as follow:

a. The class type‘s construction, destruction, assignment and copying functions should be generated only by compiler.

b. Non virtual functions and virtual base classes.

c. All the base classes and no-static member should obey above-mentioned two rules.

8. Non template function can exist with function template with same name. When overloading takes affect, Non template function will be selected preferentially. In ordinary functions argument can be converted automatically. But in function template it is impossible.

9. Nontype template parameters have some restrictions. Usually they should be const int type(including enum ,static class member and extern point or reference type).

template<char const* name>

class Myclass { };

extern char const s[] = “hello”; // without this declaration, an error will output

Myclass<s> x;

10. A function produced by function template will never looked on as same as ordinary function, even if they have same type and name. This rule will cause the following result:

a. Those functions generated by member function template will not override virtual functions.

b. Those functions generated by constructor template will not regard as default copy function.

11. To judge if a type can be converted to another type We have the following method:

template<class T,class U>

class Conversion {

typedef char Small; // the length is 1

class Big { char dummy[2]; }; // the length is 2

static Small Test(U);

static Big Test(…);

static T MakeT();

public:

enum { exists = sizeof(Test(MakeT()) == sizeof(Small)};

};

Use method: cout << Conversion<double,int>::exists;

With help of “Conversion” it’s easy to judge extend-relationship between two classes:

//partial specialization

template<class T>

class Conversion<T,T> {

public:

enum { exists =1, exists2Way =1,sameType = 1 };

};

#define SUPERSUBCLASS(T,U) \

(Conversion<const U*,const T*>::exists

&& !Conversion<const T*,const void*>::sameType)

Specification from <<modern c++ design>> 2001

12. c++ exception process system require all the objects in stack those destructor be declared as public.

Wednesday, December 06, 2006

Using Springframework And AspectJ To Apply Service Injection

Why I combine Spring and AspectJ to inject service?
At first I demonstrate an example.

Listing 1-------------------------------------------------------------

public interface CalculationService {

public BigDecimal calculate(BigDecimal costedFee);

}

public class CalculationServiceImpl1 implements CalculationService {

public BigDecimal calculate(BigDecimal costedFee) {

return costedFee.multiply(new BigDecimal(0.8));

}

public String toString() {

return new String("CalculationServiceImpl1");

}

}

public class CalculationServiceImpl2 implements CalculationService {

public BigDecimal calculate(BigDecimal costedFee) {

return costedFee.multiply(new BigDecimal(0.5));

}

public String toString() {

return new String("CalculationServiceImpl2");

}

}

----------------------------------------------------------------------

CalculationService is the service I add to clients who will use this service. CalculationServiceImpl1 and CalculationServiceImpl2 are different implements of CalculationService.

Listing 2-------------------------------------------------------------

@Target({ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Inherited

public @interface NeedMessageOutput {

}

----------------------------------------------------------------------

Those methods have NeedMessageOutput annotation will print the specific service clients used.

Listing 3-------------------------------------------------------------

import java.math.BigDecimal;

public class Client {

private BigDecimal costedFee;

private BigDecimal paymentFee;

private CalculationService currValuationService;

public void setCostedFee(BigDecimal costedFee) {

this.costedFee = costedFee;

}

public CalculationService getCurrValuationService() {

return currValuationService;

}

public void setCurrValuationService(CalculationService currValuationService) {

this.currValuationService = currValuationService;

}

public BigDecimal getPaymentFee() {

return paymentFee;

}

public void setPaymentFee(BigDecimal paymentFee) {

this.paymentFee = paymentFee;

}

@NeedMessageOutput

public void calculatePaymentFee() {

setPaymentFee(getCurrValuationService().calculate(costedFee));

}

@NeedMessageOutput

public void calculatePaymentFee(int discount) {

setPaymentFee((getCurrValuationService().calculate(costedFee)).multiply(new BigDecimal((100-discount)/100)));

}

}

----------------------------------------------------------------------

Client Object depends on CalculationService to get specific price. Overload methods calculatePaymentFee() with @NeedMessageOutput annotation. Annotation is a kind of metadata. Metadata can be seen as values in additional dimensions. Annotation help the name of method or field clean, and method or field can express their meaning just exactly like their name. Another functions often used by any methods like log messages, security validation can be marked by annotation. It is a suitable facility used by AOP. Here I use AspectJ to add aspect to those methods with annotation.

Listing 4-------------------------------------------------------------

public aspect CaseCalculateServiceMgmt {

private CalculationService service;

public void setService(CalculationService service) {

this.service = service;

}

pointcut caseInitialization(Client simpleClient)

: initialization(Client+.new(..)) && this(simpleClient);

pointcut repeatableInjectedService(Client simpleClient) : execution(@NeedMessageOutput * Client+.*(..)) && this(simpleClient);

after(Client simpleClient) : caseInitialization(simpleClient) {

simpleCase.setCurrValuationService(service);

}

after(Client simpleClient) : repeatableInjectedService(simpleClient) {

System.out.println("using " + simpleClient.getCurrValuationService().toString() + "to calculate price");

}

}

----------------------------------------------------------------------

Simply I use dependency inject service to the aspect itself, then aspect CaseCalculateServiceMgmt add service to client. Every client and its subclass's calculationservice is injected by pointcut caseInitialization. pointcut repeatableInjectedService affects methods with annotation @NeedMessageOutput.

The following listing is spring configuration xml file for aspect CaseCalculateServiceMgmt

Listing 5-------------------------------------------------------------


 
<beans>
<bean id="calculationService"
class="CaseCalculateServiceMgmt"
factory-method="aspectOf">
<property name="service">
<ref bean="serviceImpl"/>
</property>
</bean>

<bean id="serviceImpl"
class="CalculationServiceImpl1">
</bean>
</beans>



----------------------------------------------------------------------

In this case, AspectJ aspects is singleton, with one instance per class loader. This single instance is responsible for advising multiple object instances. A Spring IoC container cannot instantiate an aspect, as aspects don't have callable constructors. But it can obtain a reference to an aspect using the static aspectOf() method that AspectJ defines for all aspects, and it can inject dependencies into that aspect. So here please pay attention to “factory-method="aspectOf"” in the xml configration file. If aspects have other lifecyles such as perthis,pertarget and percflow aspects. The situation is different.(considering aspect implement ApplicationContextAware interface)

ok,go back to the question I introduced at the start of this article. AspectJ here acted as the first broker, it determined all initialization join points for client objects need this service, and Springframework took care of the second broker responsibility, Dependency Injection inject service to aspect. Both two levels of broker define the service from spring configuration file and the aim of the service.