Gangmax Blog

自由之思想,独立之精神

Spring AOP

| Comments

This is an example how to use Spring AOP.

Here is the original code before using Spring AOP.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*
 * BaseDynamicDataSourceHandlerImpl.java: This class is the base class for
 * all the handler classes which need the dynamic DataSource support. In each
 * subclass handling method, it should invoke the "setDataSourceContext(...)"
 * method to switch the DataSource(by passing the "mallId" argument from
 * the handling method's arguments).
 */
public abstract class BaseDynamicDataSourceHandlerImpl {
    ...

    /**
     * Set the DataSource context according to the current mall.
     *
     * @param mallId
     */
    public void setDataSourceContext(Integer mallId) {
        ...
    }

    ...
}



/*
 * CustomerFlowHandlerImpl.java: A subclass of "BaseDynamicDataSourceHandlerImpl"
 * class.
 */
@Component
public class CustomerFlowHandlerImpl extends BaseDynamicDataSourceHandlerImpl implements CustomerFlowHandler {
    ...

    @Override
    public DataResult<String, Integer> getCustomerFlowTrendHistory(Integer mallId, CustomerType customerType,
                                                                   Integer floorId, Integer historyDayCount) {
        setDataSourceContext(mallId);
        ...
    }

    @Override
    public DataResult<String, Integer> getCustomerFlowTrendAverage(Integer mallId, CustomerType customerType,
                                                                   Integer floorId, Integer historyDayCount) {
        setDataSourceContext(mallId);
        ...
    }

    @Override
    public DataResult<String, Integer> getEnterShopCustomerAmountHistory(Integer mallId, CustomerType customerType,
                                                                         Integer floorId, Integer historyDayCount) {
        setDataSourceContext(mallId);
        ...
    }

    @Override
    public DataResult<String, Integer> getEnterShopCustomerAmountAverage(Integer mallId, CustomerType customerType,
                                                                         Integer floorId, Integer historyDayCount) {
        setDataSourceContext(mallId);
        ...
    }

    ...
}

According to the “DRY” principle, this should be improved. The following solution is done with Spring AOP. The solution comes from here and here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/*
 * DynamicDataSourceAspect.java: The Aspect implementation which defines the pointcut
 * for each public method in any subclass of "BaseDynamicDataSourceHandlerImpl", and
 * makes the invocation of the "setDataSourceContext"method.
 */
@Component
@Aspect
public class DynamicDataSourceAspect {
    @Before("execution(public * com.jcloud.zhike.handler.impl.BaseDynamicDataSourceHandlerImpl+.*(..)) && args(mallId,..)")
    public void setDynamicDataSource(JoinPoint joinPoint, Integer mallId) {
        BaseDynamicDataSourceHandlerImpl target = (BaseDynamicDataSourceHandlerImpl)joinPoint.getTarget();
        target.setDataSourceContext(mallId);
    }
}



/*
 * CustomerFlowHandlerImpl.java: Now the "setDataSourceContext(...)" invocation lines can be removed.
 */
@Component
public class CustomerFlowHandlerImpl extends BaseDynamicDataSourceHandlerImpl implements CustomerFlowHandler {
    ...

    @Override
    public DataResult<String, Integer> getCustomerFlowTrendHistory(Integer mallId, CustomerType customerType,
                                                                   Integer floorId, Integer historyDayCount) {
        ...
    }

    @Override
    public DataResult<String, Integer> getCustomerFlowTrendAverage(Integer mallId, CustomerType customerType,
                                                                   Integer floorId, Integer historyDayCount) {
        ...
    }

    @Override
    public DataResult<String, Integer> getEnterShopCustomerAmountHistory(Integer mallId, CustomerType customerType,
                                                                         Integer floorId, Integer historyDayCount) {
        ...
    }

    @Override
    public DataResult<String, Integer> getEnterShopCustomerAmountAverage(Integer mallId, CustomerType customerType,
                                                                         Integer floorId, Integer historyDayCount) {
        ...
    }

    ...
}

More basic concepts about Spring AOP can be found in the offical document here.

Comments