1 目标对象
package com.musi.bean;
import org.springframework.stereotype.Component;
@Component
public class Animal {
public void run(){
System.out.println("animal is running .....");
}
public void run(String name){
System.out.println(name+" is running ........");
}
public void run(int times){
System.out.println("animal running times:"+times);
}
}
2 切面
package com.musi.aop.annotationaspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class AnimalAspect {
@Before("execution(* com.musi.bean.Animal.run(..))")
public void beforeRunning(){
System.out.println("annotation before running .......");
}
@After("execution(* com.musi.bean.Animal.run(..))")
public void afterRunning(){
System.out.println("annotation after running .......");
}
@AfterReturning("execution(* com.musi.bean.Animal.run(..))")
public void afterReturning(){
System.out.println("annotation afterReturning running .......");
}
@AfterThrowing("execution(* com.musi.bean.Animal.run(..))")
public void afterThrowing(){
System.out.println("annotation afterThrowing running .......");
}
}
简化写法:
package com.musi.aop.annotationaspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class AnimalAspectSimple {
@Pointcut("execution(* com.musi.bean.Animal.run())")
public void run(){}
@Before("run()")
public void beforeRunning(){
System.out.println("before running .......");
}
@After("run()")
public void afterRunning(){
System.out.println("after running .......");
}
@AfterReturning("run()")
public void afterReturning(){
System.out.println("afterReturning running .......");
}
@AfterThrowing("run()")
public void afterThrowing(){
System.out.println("afterThrowing running .......");
}
}
备注:上述代码中使用了@Pointcut注解,其中performance()方法的名称和实际内容并不重要,在这里它实际上应该是空的,它本身只不过是一个标识,供@Pointcut注解依附.需要注意的是此时除了注解和没有实际操作的performance()方法,Audience类依然是一个pojo,这与普通的Java类并没有什么区别,只不过通过注解表名会被最为切面使用.
3 如果就此止步的话,Audience只会是spring容器中普通的bean,即便使用了AspectJ,但它并不会被视为切面,还需要另作配置.使用Javaconfig的话,可以在配置类的类级别上通过使用EnableAspectJ-AutoProxy注解启用自动代理功能,代码如下:
package com.musi.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.musi")
public class SystemConfig {
}
相应的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">
<context:component-scan base-package="com.musi"/>
<aop:aspectj-autoproxy />
</beans>
4 测试类
package com.musi.test.bean;
import com.musi.aop.annotationaspect.Encoreable;
import com.musi.bean.Animal;
import com.musi.config.SystemConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SystemConfig.class)
public class SpringBeanTest {
@Autowired
private Animal animal;
@Test
public void test(){
animal.run();
}
}
使用xml配置时的测试类
package com.musi.test.bean;
import com.musi.bean.Animal;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:application.xml"})
public class SpringXmlTest {
@Autowired
private Animal animal;
@Test
public void test(){
animal.run();
}
}
5 创建环绕通知
package com.musi.aop.annotationaspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class AnimalRoundAspect {
@Pointcut("execution(* com.musi.bean.Animal.run(..))")
public void run(){}
@Around("run()")
public void aroundRunning(ProceedingJoinPoint pjp){
try {
System.out.println("around before ....");
pjp.proceed();
System.out.println("around after ....");
}catch (Throwable throwable) {
System.out.println("around trowing ....");
throwable.printStackTrace();
}
}
}
测试类同上
6 处理通知中的参数
package com.musi.aop.annotationaspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class AnimalArgsAspect {
@Pointcut("execution(* com.musi.bean.Animal.run(int))&&args(times)")
public void run(int times){}
@Before("run(times)")
public void beforeRunning(int times){
System.out.println("before running times:"+times);
}
@After("run(times)")
public void afterRunning(int times){
System.out.println("after running times:"+times);
}
@AfterReturning("run(times)")
public void afterReturning(int times){
System.out.println("afterReturning running times:"+times);
}
@AfterThrowing("run(times)")
public void afterThrowing(int times){
System.out.println("afterThrowing running times:"+times);
}
}
测试类
package com.musi.test.bean;
import com.musi.bean.Animal;
import com.musi.config.SystemConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SystemConfig.class)
public class SpringBeanArgsTest {
@Autowired
private Animal animal;
@Test
public void test(){
animal.run(11);
}
}
7 通过注解引入新功能
- 创建引入的代理
package com.musi.aop.annotationaspect;
public interface Encoreable {
void jump();
}
- 代理默认实现类
package com.musi.aop.annotationaspect;
public class EncoreableImpl implements Encoreable {
public void jump() {
System.out.println("this is EncoreableImpl.....");
}
}
3)通过DeclareParents设置代理
package com.musi.aop.annotationaspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class EncoreableIntroducer {
@DeclareParents(value="com.musi.bean.Animal",defaultImpl=EncoreableImpl.class)
public static Encoreable encoreable;
}
说明:@DeclareParents注解有三部分组成:
value属性指定了哪种类型的bean要引入该接口.在本例中也就是Animal.(如果Animal是接口的话可以在Animal后加上加号,即"com.musi.bean.Animal+",表示是Animal的所有子类型,而不是Animal本身)
defaultImpl属性指定了为引入功能提供实现的类.在这里我们指定的是DefaultEncoreable提供实现
@DeclareParents注解所标注的静态属性指明了要引入接口.在这里我们引入的是Encoreable接口.
此外,我们需要将EncoreableIntroducer声明为一个bean:
4)测试类
package com.musi.test.bean;
import com.musi.aop.annotationaspect.Encoreable;
import com.musi.bean.Animal;
import com.musi.config.SystemConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SystemConfig.class)
public class SpringBeanTest {
@Autowired
private Animal animal;
@Test
public void test(){
animal.run();
Encoreable encoreable = (Encoreable)animal;
encoreable.jump();
}
}