注解配置业务类

使用@Component("s") 注解ProductService 类

package com.how2java.service;

import org.springframework.stereotype.Component;

@Component("s")
public class ProductService {
    public void doSomeService(){
        System.out.println("doSomeService");
    }

}

注解配置切面

@Aspect 注解表示这是一个切面
@Component 表示这是一个bean,由Spring进行管理
@Around(value = "execution(* com.how2java.service.ProductService.*(..))") 表示对com.how2java.service.ProductService 这个类中的所有方法进行切面操作

package com.how2java.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggerAspect {

    @Around(value = "execution(* com.how2java.service.ProductService.*(..))")
    public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("start log:" + joinPoint.getSignature().getName());
        Object object = joinPoint.proceed();
        System.out.println("end log:" + joinPoint.getSignature().getName());
        return object;
    }
}

applicationContext.xml

去掉原有信息,添加如下3行

<context:component-scan base-package="com.how2java.aspect"/>
<context:component-scan base-package="com.how2java.service"/>

扫描包com.how2java.aspect和com.how2java.service,定位业务类和切面类

<aop:aspectj-autoproxy/>

找到被注解了的切面类,进行切面配置

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/aop
                http://www.springframework.org/schema/aop/spring-aop.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.how2java.aspect"/> <context:component-scan base-package="com.how2java.service"/> <aop:aspectj-autoproxy/> </beans>

测试运行

package com.how2java.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.how2java.service.ProductService;

public class TestSpring {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                new String[] { "applicationContext.xml" });
        ProductService s = (ProductService) context.getBean("s");
        s.doSomeService();
    }
}

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

 在how2j 网站学习spring框架时,发现有网友留了一些问题,这里我们拿出来分享一下

1. 为什么用注解方式跑程序比用xml配置要慢?

xml文件的形式,系统只需要解析xml文件中的内容,你需要自己去管理xml文件。而注解最终要调用反射,反射很耗时间的,换来的是不需要去管理xml文件,二者各有优缺点,看情况选择合适的方式。

2. 假如一个业务有两个切面如何区分先后顺序?比较重要

使用xml配置的时候,在定义切面时候,如果通知的类型相同,可以加上order定义多个切面的执行顺序,这里有两种情况:

<aop:aspect id="logAspect2" ref="loggerAspect2" order="1">
     <aop:before pointcut-ref="loggerCutpoint" method="log"/>
</aop:aspect>

<aop:aspect id="logAspect3" ref="loggerAspect3" order="2">
     <aop:before pointcut-ref="loggerCutpoint" method="log"/>
</aop:aspect>    

上面的通知类型都是before,order的数值越小越先执行!!!

<aop:aspect id="logAspect2" ref="loggerAspect2" order="1">
     <aop:after pointcut-ref="loggerCutpoint" method="log"/>
</aop:aspect>

<aop:aspect id="logAspect3" ref="loggerAspect3" order="2">
     <aop:after pointcut-ref="loggerCutpoint" method="log"/>
</aop:aspect>    

上面的通知类型都是after,order的数值越大越先执行!!!

若在定义切面时候,如果通知的类型不同,则无论怎样定义order都无法决定多个切面的执行顺序

<!--该切面order="1",但通知是after类型-->
<aop:aspect id="logAspect2" ref="loggerAspect2" order="1"> <aop:after pointcut-ref="loggerCutpoint" method="log"/> </aop:aspect>
<!--该切面order="2",但通知是before类型-->
<aop:aspect id="logAspect3" ref="loggerAspect3" order="2">
   <aop:before pointcut-ref="loggerCutpoint" method="log"/>
</aop:aspect>

这种情况切面的执行顺序是按通知的类型决定的!!!

用注解的方式定义切面,执行的先后顺序其原理和xml配置一样。

3. 如何把一个切面织入两个不同的业务类中?

可在切面中加入

@Around(value = "execution(* com.java.ProductService.*(..)) || execution(* com.java.service.ProductService2.*(..))")

如果分开写,会报错,例如 

@Around(value = "execution(* com.java.ProductService.*(..))"
@Around(value = "execution(* com.java.ProductService2.*(..))"    
01-01 21:29