(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..