Spring AOP 基本用法

导入
aopalliance-1.0.jar
aspectjrt-1.7.4.jar
aspectjweaver-1.7.4.jar

Spring AOP 的使用可以注解或是xml配置文件的形式,使用AOP尽量使用注解的形式

AOP注解的方式

定义切面和连接点 LogAspect

package com.shpun.aop;
import org.aspectj.lang.annotation.*;

@Aspect
public class LogAspect {

    /*
    或使用@Pointcut,不用每个都写那么长的类名

    @Pointcut("execution(* com.shpun.service..*(..))")
    public void print(){}
    @Before("print()")
    @After("print()")
    @AfterReturning("print()")
    @AfterThrowing("print()")
    */

    // 切入点为 com.shpun.service包下的所有类的所有方法 
    // 在被代理对象的方法 前 先调用 
    @Before("execution(* com.shpun.service..*(..))")
    public void before(){
        System.out.println("LogAspect before ... ");
    }
    // 在被代理对象的方法 后 调用  
    @After("execution(* com.shpun.service..*(..))")
    public void after(){
        System.out.println("LogAspect after ... ");
    }
    // 在被代理对象的方法 正常返回 后调用  
    @AfterReturning("execution(* com.shpun.service..*(..))")
    public void afterReturning(){
        System.out.println("LogAspect afterReturning ... ");
    }
    // 在被代理对象的方法 抛出异常 后调用  
    @AfterThrowing("execution(* com.shpun.service..*(..))")
    public void afterThrowing(){
        System.out.println("LogAspect afterThrowing ... ");
    }
}

接口和实现类

package com.shpun.service;
public interface ShowService {
    void showCustomer(Customer customer);
}

package com.shpun.service;

@Service
public class ShowServiceImpl implements ShowService {
    @Override
    public void showCustomer(Customer customer) {
        System.out.println("ShowServiceImpl : id: "+customer.getId()+" name: "+customer.getName()+" note: "+customer.getNote());
    }
}

JavaBean

package com.shpun.entity;
public class Customer {
    private String id;
    private String name;
    private String note;
    /*getter setter*/
}

纯注解的方式使用,需要写一个配置类进行配置

package com.shpun.aop;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.shpun.service")
public class AOPConfig {

    @Bean
    public LogAspect getLogAspect(){
        return new LogAspect();
    }
}

或者是使用xml配置文件配置



    
    
    
    

测试

public class TestAOP {
    public static void main(String[] main){
        ApplicationContext context = new AnnotationConfigApplicationContext(AOPConfig.class);
        //ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        ShowService showServiceImpl = context.getBean(ShowService.class);

        Customer customer = new Customer();
        customer.setId("1");
        customer.setName("AOP");
        customer.setNote("AOP Test");
        showServiceImpl.showCustomer(customer);

        System.out.println("测试异常情况");
        customer = null;
        showServiceImpl.showCustomer(customer);
    }
}

输出结果

ShowServiceImpl : id: 1 name: AOP note: AOP Test
LogAspect after ... 
LogAspect afterReturning ... 
测试异常情况
LogAspect before ... 
LogAspect after ... 
LogAspect afterThrowing ... 

再使用Around,在LogAspect添加

    @Around("execution(* com.shpun.service..*(..))")
    public void around(ProceedingJoinPoint jp){
        System.out.println("around before ...");
        try{
            jp.proceed();
        }catch (Throwable e){
            e.printStackTrace();
        }
        System.out.println("around after ...");
    }

输出结果

around before ...
LogAspect before ... 
ShowServiceImpl : id: 1 name: AOP note: AOP Test
around after ...
LogAspect after ... 
LogAspect afterReturning ... 
测试异常情况
around before ...
LogAspect before ... 
around after ...
LogAspect after ... java.lang.NullPointerException
                                
LogAspect afterReturning ... 

ps:

当我有多个ShowService的实现类时,比如多一个实现类ShowServiceTwoImpl,并加上@Service

1.如果实现类ShowServiceTwoImpl,class没加上@Service,继续使用如下方式获取bean,则获取的是ShowServiceImpl;加上@Service,则会得到异常,原因是有两个实现类,Spring不知获取哪一个

ShowService showServiceImpl = context.getBean(ShowService.class);

NoUniqueBeanDefinitionException: No qualifying bean of type 'com.shpun.service.ShowService' 
available: expected single matching bean but found 2: showServiceImpl,showServiceTwoImpl

2.搜索结果显示该错误多是@Autowired是出现,有的说是Spring没有扫描到,但我换成xml形式扫描,错误一样。未知

ShowService showServiceImpl = context.getBean(ShowServiceImpl.class);

NoSuchBeanDefinitionException: No qualifying bean of type 'com.shpun.service.ShowServiceImpl' available

3.因为@Service默认使用类名首字母小写的形式生成bean,尝试类名查找

ShowService showServiceImpl = context.getBean("showServiceImpl",ShowServiceImpl.class);

BeanNotOfRequiredTypeException: Bean named 'showServiceImpl' is expected to be of type 'com.shpun.service.ShowServiceImpl' 
but was actually of type 'com.sun.proxy.$Proxy21'

BeanNotOfRequiredTypeException 切面异常

目前使用的是配置类的形式,所以在AOPConfig里面

@EnableAspectJAutoProxy(proxyTargetClass = true)

若使用xml配置文件的形式,改为


测试AOP成功

ShowService showServiceImpl = context.getBean("showServiceImpl",ShowServiceImpl.class);
ShowService showServiceTwoImpl = context.getBean("showServiceTwoImpl",ShowServiceTwoImpl.class);

输出结果

LogAspect before ... 
ShowServiceImpl : id: 1 name: AOP note: AOP Test
LogAspect after ... 
LogAspect afterReturning ... 
LogAspect before ... 
two com.shpun.entity.Customer@7c83dc97
LogAspect after ... 
LogAspect afterReturning ...
测试异常情况
LogAspect before ... 
LogAspect after ... 
LogAspect afterThrowing ... 

一个接口的多个实现类,通过getBean使用时,需要proxy-target-class="true"。

 默认jdk代理
 设置为true,为cglib代理

你可能感兴趣的:(Spring AOP 基本用法)