spring学习笔记之AOP

(1)基于配置文件的AOP:

基本术语:

join point(连接点)

pointcut(切入点)

advice(通知)

aspect(方面)

introduce(引入):在不修改类的前提下为类添加新的方法和属性

AOP proxy (aop代理)

weaving(织入)

Advice:

  before advice      前置通知

  after returning advice  返回后通知

  after throwing advice      抛出异常后通知

  after (finally) advice   后通知

  around advice      环绕通知

 类一:aspect.java:

package xz.learn.pointcut;

public class aspect {
    public void before(){
        System.out.println("before........");
    }
}

类二:Say.java

package xz.learn.pointcut;

public class Say {
    public void say() {
        System.out.println("pointcut-------what matter???");
    }
    
    public void haha() {
        System.out.println("hahahahhashahah==============");
    }
    
    public void gagagag() {
        System.out.println("gagagaggagagagag=============");
    }
}

测试类:xzTest.java

package xz.learn.test;

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

import xz.learn.ioc.Man;
import xz.learn.pointcut.Say;
import xz.learn.pointcut.aspect;

public class xzTest {
    public static void main(String[] args){
        
        ApplicationContext apc= new ClassPathXmlApplicationContext("xz/learn/pz/spring-aop-schema.xml");
        
        Say say=(Say)apc.getBean("say");
        
        say.say();
        
        say.haha();
        
        say.gagagag();
    }
}

配置文件:spring-aop-schema.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"
    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.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <bean class="xz.learn.pointcut.aspect" id="myAspect"></bean>
    <bean class="xz.learn.pointcut.Say" id="say"></bean>
    
    <aop:config>
        <aop:aspect id="xzAOP" ref="myAspect">
            <aop:pointcut expression="execution(* xz.learn.pointcut.Say.*(..))" id="xzPointCut"/>
            <aop:before method="before"    pointcut-ref="xzPointCut"/>
        </aop:aspect>
    </aop:config>
        
</beans>

执行结果:

before........
pointcut-------what matter???
before........
hahahahhashahah==============
before........
gagagaggagagagag=============
小结:由此可见,aop定义了一个pointcut,其中可以进行多种方法或者函数的拦截。交有切面的函数进行处理。

 遇见问题:在使用Dog类作为切入点拦截对象时报错: ClassCastException

查到问题发现:

  因为spring内部也是使用的jdk的动态代理,而其中proxy是使用的class.getInterfaces()方法获取的对象方法,所以在使用ApplicationContext.getBean(“bean”)方法时都是返回的对象的接口,然后再通过转型来获得bean所指定的对象实例。因此要将InterfaceImpl加入xml配置文件中,否则报错。

 

使用Aspectj

1、xzAspect.java

 

package xz.learn.aspectj;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class xzAspect {
    
    @Before("execution(* xz.learn.cases.Dog.*(..))")
    public void before() {
        System.out.println("before..");
    }
    
    @AfterReturning(pointcut="execution(* xz.learn.cases.Dog.*(..))",returning="returnValue")
    public void afterReturning(Object returnValue) {
        System.out.println("after return"+returnValue);
    }
    
    @AfterThrowing(pointcut="execution(* xz.learn.cases.Dog.*(..))",throwing="exception")
    public void throwEx(RuntimeException exception) {
        System.out.println("after throwing!"+exception);
    }
    
    @Around("execution(* xz.learn.cases.Dog.*(..))")
    public Object aroundAdvice (ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("111111111111111111111111");
        Object obj=pjp.proceed();
        System.out.println("222222222222222222222222");
        return obj;
    }
}

 

2、Dog.java

package xz.learn.cases;

import org.springframework.stereotype.Service;

@Service
public class Dog{

    public String eat(String str) {
        System.out.println("This is a Dog!eat"+str);
        //throw new RuntimeException();
        return "dog wangwang..";
    }

}

3、TestAspectJ.java

package xz.learn.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;

import xz.learn.base.UnitTestBase;
import xz.learn.cases.Dog;


@RunWith(BlockJUnit4ClassRunner.class)
public class TestAspectJ extends UnitTestBase {
    
    public TestAspectJ() {
        super("classpath:spring-aop-aspectj.xml");
    }
    
    @Test
    public void test() {
        Dog dog = getBean("dog");
        dog.eat("骨头");
    }
    
}

4、UnitTestBase.java

package xz.learn.base;

import org.junit.After;
import org.junit.Before;
import org.springframework.beans.BeansException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.StringUtils;

public class UnitTestBase {
    
    private ClassPathXmlApplicationContext context;
    
    private String springXmlpath;
    
    public UnitTestBase() {}
    
    public UnitTestBase(String springXmlpath) {
        this.springXmlpath = springXmlpath;
    }
    
    @Before
    public void before() {
        if (StringUtils.isEmpty(springXmlpath)) {
            springXmlpath = "classpath*:spring-*.xml";
        }
        try {
            context = new ClassPathXmlApplicationContext(springXmlpath.split("[,\\s]+"));
            context.start();
        } catch (BeansException e) {
            e.printStackTrace();
        }
    }
    
    @After
    public void after() {
        context.destroy();
    }
    
    @SuppressWarnings("unchecked")
    protected <T extends Object> T getBean(String beanId) {
        try {
            return (T)context.getBean(beanId);
        } catch (BeansException e) {
            e.printStackTrace();
            return null;
        }
    }
    
    protected <T extends Object> T getBean(Class<T> clazz) {
        try {
            return context.getBean(clazz);
        } catch (BeansException e) {
            e.printStackTrace();
            return null;
        }
    }

}

结果:
111111111111111111111111
before..
This is a Dog!eat骨头
222222222222222222222222
after returndog wangwang..

 

你可能感兴趣的:(spring学习笔记之AOP)