Spring注解配置Aop

寵の児 提交于 2020-04-05 19:49:05

之前学习了SpringAop的基本原理。http://www.cnblogs.com/expiator/p/7977975.html

现在尝试使用注解来配置SpringAop。

Aop,面向切面编程。包括切入点(PointCut)、切面(Aspect),连接点(Joinpoint)、通知(Advice)、引入(Introduction)

SpringAop注解,主要通过@AspectJ注解配置。

需要新增两个AspectJ库:aspectjweaver.jar和aspectjrt.jar,还有一个依赖aopalliance.jar包。

Aop注解配置如下:

@Component
@Aspect
public class MyInterceptor {
    @Pointcut("execution (* cn.itcast.service.impl.UserServiceImpl.*(..))")
    private void cutMethod() {} // 声明一个切入点,cutMethod为切入点名称
    
    // 声明该方法是一个前置通知:在目标方法开始之前执行 
    @Before("cutMethod() && args(name)")
    public void doAccessCheck(String name) {
        System.out.println("前置通知:" + name);
    }
    
    @AfterReturning(pointcut="cutMethod()", returning="result")
    public void doAfterReturning(String result) {
        System.out.println("后置通知:" + result);
    }
    
    @After("cutMethod()")
    public void doAfter() {
        System.out.println("最终通知");
    }
    
    @AfterThrowing(pointcut="cutMethod()", throwing="e")
    public void doAfterThrowing(Exception e) {
        System.out.println("异常通知:" + e);
    }
       // 声明该方法是一个环绕通知,表示在目标方法前后执行设定的代码    
    @Around("cutMethod()")
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
        /**
         * 环绕通知内部一定要确保执行该方法,如果不执行该方法,业务bean中被拦截的方法就不会被执行。
         * 当执行该方法,如果后面还有切面的话,它的执行顺序应该是这样的:先执行后面的切面,如果后面没有切面了,
         * 再执行最终的目标对象的业务方法。若不执行该方法,则后面的切面,业务bean的方法都不会被执行。
         */
        System.out.println("进入方法");
        Object result = pjp.proceed();
        System.out.println("退出方法");
        
        return result;
    }
}

具体的注解如下所示:

@Aspect表明整个类是一个切面。

@Component标记该类是一个组件,spring扫描注解配置时,会标记这些类要生成bean

@Pointcut注解声明一个切入点。

我们可利用方法签名来编写切入点表达式。

最典型的切入点表达式是根据方法的签名来匹配各种方法:
execution (* cn.itcast.service.impl.UserServiceImpl.*(..)):匹配UserServiceImpl类中声明的所有方法。第一个*代表任意修饰符及任意返回值类型,第二个*代表任意方法,..匹配任意数量任意类型的参数,若目标类与该切面在同一个包中,可以省略包名。
execution public * cn.itcast.service.impl.UserServiceImpl.*(..):匹配UserServiceImpl类中的所有公有方法。
execution public double cn.itcast.service.impl.UserServiceImpl.*(..):匹配UserServiceImpl类中返回值类型为double类型的所有公有方法。
execution public double cn.itcast.service.impl.UserServiceImpl.*(double, ..):匹配UserServiceImpl类中第一个参数为double类型,后面不管有无参数的所有公有方法,并且该方法的返回值类型为double类型。
execution public double cn.itcast.service.impl.UserServiceImpl.*(double, double):匹配UserServiceImpl类中参数类型为double,double类型的,并且返回值类型也为double类型的所有公有方法。

前置通知:表示在目标方法之前执行设定的代码。

环绕通知:表示在目标方法前后执行设定的代码。

 其他的源码如下:

UserService.java如下:

public interface UserService {
    public void save(String name);
    public void update(String name, Integer id);
    public String getUserName(Integer id);
}

UserServiceImpl.java如下:

@Service
public class UserServiceImpl implements UserService {
    @Override
    public void save(String name) {
//        throw new RuntimeException("我是异常");
         System.out.println("我是save()方法");
    }

    @Override
    public void update(String name, Integer id) {
        System.out.println("我是update()方法");
    }

    @Override
    public String getUserName(Integer id) {
        System.out.println("我是getUserName()方法");
        return "xxx";
    }

}

beans.xml配置文件如下:

<?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:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--开启aop代理-->
    <aop:aspectj-autoproxy />
    <!--扫描目录-->
    <context:component-scan base-package="cn.itcast.service"/>

    <!--开启注解驱动-->
    <mvc:annotation-driven/>
    <!--避免IE执行AJAX时,返回JSON出现下载文件 -->
    <bean id="mappingJacksonHttpMessageConverter"
          class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
                <value>text/html;charset=UTF-8</value>
            </list>
        </property>
    </bean>
    <!-- 启动SpringMVC的注解功能,完成请求和注解POJO的映射 -->
    <bean
            class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="mappingJacksonHttpMessageConverter" /> <!-- JSON转换器 -->
            </list>
        </property>
    </bean>
</beans>

最后,进行单元测试。UserServiceImplTest  如下所示:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:beans.xml"})
public class UserServiceImplTest {
    @Autowired
   private UserService userService;

@Before
public void before() throws Exception { 
} 

@After
public void after() throws Exception { 
} 

/** 
* 
* Method: save(String name) 
* 
*/ 
@Test
public void testSave() throws Exception { 
//TODO: Test goes here...
    userService.save("lin");
} 

} 

测试结果:

 

 

参考博客:

https://blog.csdn.net/yerenyuan_pku/article/details/52865330

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!