AOP的使用场景汇总(权限验证,事务管理,日志,异常处理,性能监控)

aop的使用场景

一般来说aop的使用场景有: 事务管理, 日志操作记录, 异常处理, 缓存(页面缓存,方法缓存/查询缓存,数据缓存(对Entity/数据记录进行缓存)), 权限安全认证, Persistence 持久化, Synchronization 同步, Lazy loading 懒加载, 性能监控(方法执行时间/调用次数)

事务管理
编程式事务和声明式事务,实际中使用声明式事务
声明式事务有:配置和注解两种方式

链接1
链接2

1.事务管理
<aop:aspectj-autoproxy />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
	<tx:attributes>
	<tx:method name="save*" read-only="false" propagation="REQUIRED" />
	<tx:method name="update*" read-only="false" propagation="REQUIRED" />
	<tx:method name="delete*" read-only="false" propagation="REQUIRED" />
	<tx:method name="create*" read-only="false" propagation="REQUIRED" />
	<tx:method name="import*" read-only="false" propagation="REQUIRED" />
	<tx:method name="remove*" read-only="false" propagation="REQUIRED" />
	<tx:method name="submit*" read-only="false" propagation="REQUIRED" />
	<tx:method name="check*" read-only="false" propagation="REQUIRED" />
	</tx:attributes>
</tx:advice>
<aop:config>
 <aop:advisor pointcut="execution(* com.able.service.*.*(..))" advice-ref="txAdvice" /> 
</aop:config>

----------------------------------------------------------------------
2.日志处理
2.1 日志切面
package com.manager.aspect;
 3 import org.apache.log4j.Logger;
 4 import org.aspectj.lang.JoinPoint;
 5 import org.aspectj.lang.annotation.*;
 6 import org.springframework.stereotype.Component;
 7 
 8 import java.util.Arrays;
 9 
10 /**
11  * 日志切面
12  * Created by Kevin on 2017/10/29.
13  */
14 @Aspect
15 @Component
16 public class LogAspect {
17     /**
18      * 操作日志文件名
19      */
20     private static final String OPERATION_LOG_NAME = "operationLog";
21     private static final String LOG_FORMATTER = "%s.%s - %s";
22     Logger log = Logger.getLogger(OPERATION_LOG_NAME);
23     /**
24      * 对查询方法记录日志的切点
25      */
26     @Pointcut("execution(* com.manager..*.*Controller.query*(..))")
27     public void query(){}
28 
29     /**
30      * 对新增方法记录日志的切点
31      */
32     @Pointcut("execution(* com.manager..*.*Controller.add*(..))")
33     public void add(){}
34 
35     /**
36      * 对修改方法记录日志的切点
37      */
38     @Pointcut("execution(* com.manager..*.*Controller.update*(..))")
39     public void update(){}
40 
41     /**
42      * 对删除方法记录日志的切点
43      */
44     @Pointcut("execution(* com.manager..*.*Controller.delete*(..))")
45     public void delete(){}
46 
47     @AfterReturning(value = "query()", returning = "rvt")
48     public void queryLog(JoinPoint joinPoint, Object rvt) {
49         String className = joinPoint.getTarget().getClass().getName();
50         String methodName = joinPoint.getSignature().getName();
51         String returnResult = rvt.toString();
52         log.info(String.format(LOG_FORMATTER, className, methodName, returnResult));
53     }
54 
55     @Before("add()")
56     public void addLog(JoinPoint joinPoint) {
57         String className = joinPoint.getTarget().getClass().getName();
58         String methodName = joinPoint.getSignature().getName();
59         Object[] params = joinPoint.getArgs();
60         log.info(String.format(LOG_FORMATTER, className, methodName, Arrays.toString(params)));
61     }
62 
63     @Before("update()")
64     public void updateLog(JoinPoint joinPoint) {
65         String className = joinPoint.getTarget().getClass().getName();
66         String methodName = joinPoint.getSignature().getName();
67         Object[] params = joinPoint.getArgs();
68         log.info(String.format(LOG_FORMATTER, className, methodName, Arrays.toString(params)));
69     }
70 
71     @Before("delete()")
72     public void deleteLog(JoinPoint joinPoint) {
73         String className = joinPoint.getTarget().getClass().getName();
74         String methodName = joinPoint.getSignature().getName();
75         Object[] params = joinPoint.getArgs();
76         log.info(String.format(LOG_FORMATTER, className, methodName, Arrays.toString(params)));
77     }
78 }
<!--启用AspectJ自动代理,其中proxy-target-classtrue表示使用CGLib的代理方式,false表示JDK的代理方式,默认false-->
<aop:aspectj-autoproxy />

2.2 测试类
package com.manager.user.controller;
 2 
 3 import com.fasterxml.jackson.databind.ObjectMapper;
 4 import com.manager.user.pojo.User;
 5 import org.junit.Before;
 6 import org.junit.Test;
 7 import org.junit.runner.RunWith;
 8 import org.springframework.beans.factory.annotation.Autowired;
 9 import org.springframework.http.MediaType;
10 import org.springframework.test.context.ContextConfiguration;
11 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
12 import org.springframework.test.context.web.WebAppConfiguration;
13 import org.springframework.test.web.servlet.MockMvc;
14 import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
15 import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
16 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
17 import org.springframework.web.context.WebApplicationContext;
18 
19 import static org.junit.Assert.assertNotNull;
20 
21 /**
22  * UserController单元测试
23  * Created by Kevin on 2017/10/26.
24  */
25 @RunWith(SpringJUnit4ClassRunner.class)
26 @ContextConfiguration({"classpath*:applicationContext.xml", "classpath*:spring-servlet.xml"})
27 @WebAppConfiguration
28 public class UserControllerTest {
29     @Autowired
30     private WebApplicationContext wac;
31     private MockMvc mvc;
32 
33     @Before
34     public void initMockHttp() {
35         this.mvc = MockMvcBuilders.webAppContextSetup(wac).build();
36     }
37 
38     @Test
39     public void testQueryUsers() throws Exception {
40         mvc.perform(MockMvcRequestBuilders.get("/users"))
41                 .andExpect(MockMvcResultMatchers.status().isOk());
42     }
43 
44     @Test
45     public void testAddUser() throws Exception {
46         User user = new User();
47         user.setName("kevin");
48         user.setAge(23);
49         mvc.perform(MockMvcRequestBuilders.post("/users")
50                 .contentType(MediaType.APPLICATION_JSON_UTF8)
51                 .content(new ObjectMapper().writeValueAsString(user)))
52                 .andExpect(MockMvcResultMatchers.status().isOk())
53                 .andExpect(MockMvcResultMatchers.jsonPath("$.name").value("kevin"))
54                 .andExpect(MockMvcResultMatchers.jsonPath("$.age").value(23));
55     }
56 
57     @Test
58     public void testQueryUserById() throws Exception {
59         User user = new User();
60         user.setId(8);
61         mvc.perform(MockMvcRequestBuilders.get("/users/" + user.getId()))
62                 .andExpect(MockMvcResultMatchers.status().isOk())
63                 .andExpect(MockMvcResultMatchers.jsonPath("$.name").value("kevin"))
64                 .andExpect(MockMvcResultMatchers.jsonPath("$.age").value(23));
65 
66     }
67 
68     @Test
69     public void testUpdateUserById() throws Exception {
70         User user = new User();
71         user.setId(9);
72         user.setName("tony");
73         user.setAge(99);
74         mvc.perform(MockMvcRequestBuilders.put("/users/" + user.getId())
75                 .contentType(MediaType.APPLICATION_JSON_UTF8)
76                 .content(new ObjectMapper().writeValueAsString(user)))
77                 .andExpect(MockMvcResultMatchers.status().isOk());
78     }
79 
80     @Test
81     public void testDeleteUserById() throws Exception {
82         long id = 10;
83         mvc.perform(MockMvcRequestBuilders.delete("/users/" + id))
84                 .andExpect(MockMvcResultMatchers.status().isOk());
85     }
86 }

3.性能监控
先配置pom文件如下:
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>io.dropwizard.metrics</groupId>
            <artifactId>metrics-core</artifactId>
            <version>
                ${metrics.version}
            </version>
        </dependency>
        <dependency>
            <groupId>io.dropwizard.metrics</groupId>
            <artifactId>metrics-annotation</artifactId>
            <version>${metrics.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.7</version>
        </dependency>
----------------------------------------------------------------------   
3.1 定义Configuration 配置类
@Configuration
@ComponentScan({ "com.keevol.springboot.metrics.lifecycle",
        "com.keevol.springboot.metrics.aop" })
@AutoConfigureAfter(AopAutoConfiguration.class)
public class DropwizardMetricsMBeansAutoConfiguration {
    @Value("${metrics.mbeans.domain.name:com.keevol.metrics}")
    String metricsMBeansDomainName;
    @Autowired
    MBeanServer mbeanServer;
    @Autowired
    MetricRegistry metricRegistry;

    @Bean
    public JmxReporter jmxReporter() {
        JmxReporter reporter = JmxReporte.forRegistry(metricRegistry)
                .inDomain(metricsMBeansDomainName).registerWith(mbeanServer)
                .build();
        return reporter;
    }
}
将这个配置类添加到 META-INF/spring.factories:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.keevol.springboot.metrics.autocfg.DropwizardMetricsMBeansAutoConfiguration
----------------------------------------------------------------------
3.2 定义一个监控切面
@Component
@Aspectpublic
class AutoMetricsAspect {
    protected ConcurrentMap<String, Meter> meters = new ConcurrentHashMap<>();
    protected ConcurrentMap<String, Meter> exceptionMeters = new ConcurrentHashMap<>();
    protected ConcurrentMap<String, Timer> timers = new ConcurrentHashMap<>();
    protected ConcurrentMap<String, Counter> counters = new ConcurrentHashMap<>();
    @Autowired
    MetricRegistry metricRegistry;

    @Pointcut(value = "execution(public * *(..))")
    public void publicMethods() {
    }

    @Before("publicMethods() && @annotation(countedAnnotation)")
    public void instrumentCounted(JoinPoint jp, Counted countedAnnotation) {
        String name = name(jp.getTarget().getClass(), StringUtils.hasLength(countedAnnotation.name()) ? countedAnnotation.name() : jp.getSignature().getName(), "counter");
        Counter counter = counters.computeIfAbsent(name, key -> metricRegistry.counter(key));
        counter.inc();
    }   
   
    @Before("publicMethods() && @annotation(meteredAnnotation)")
    public void instrumentMetered(JoinPoint jp, Metered meteredAnnotation) {
        String name = name(jp.getTarget().getClass(), StringUtils.hasLength(meteredAnnotation.name()) ? meteredAnnotation.name() : jp.getSignature().getName(), "meter");
        Meter meter = meters.computeIfAbsent(name, key -> metricRegistry.meter(key));
        meter.mark();
    }   
    @AfterThrowing(pointcut = "publicMethods() && @annotation(exMe-teredAnnotation)", throwing = "ex")
    public void instrumentExceptionMetered(JoinPoint jp, Throwable ex, ExceptionMetered exMeteredAnnotation) {
        String name = name(jp.getTarget().getClass(), StringUtils.hasLength(exMeteredAnnotation.name()) ? exMeteredAnnotation.name() : jp.getSignature().getName(), "meter", "exception");
        Meter meter = exceptionMeters.computeIfAbsent(name, meterName -> metricRegistry.meter(meterName));
        meter.mark();
    }   
    @Around("publicMethods() && @annotation(timedAnnotation)")
    public Object instrumentTimed(ProceedingJoinPoint pjp, Timed timedAnnotation) throws Throwable {
        String name = name(pjp.getTarget().getClass(), StringUtils.hasLength(timedAnnotation.name()) ? timedAnnotation.name() : pjp.getSignature().getName(), "timer");
        Timer timer = timers.computeIfAbsent(name, inputName -> metricRegistry.timer(inputName));
        Timer.Context tc = timer.time();
        try {
            return pjp.proceed();
        } finally {
            tc.stop();
        }
    }
}
----------------------------------------------------------------------
3.3具体业务service
@Component
public class MockService {
    @Timed
    @Counted
    public void doSth() {
        System.out.println("just do something.");
    }
} 

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


4.权限验证
使用拦截器实现 token登录验证
链接

在这里插入图片描述

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值