SpringAOP

来源:互联网 发布:盘锦兼职淘宝客服招聘 编辑:程序博客网 时间:2024/06/08 04:17

SpringAOP构建在动态代理之上,因此Spring对AOP的支持局限于方法拦截。首先需要引入依赖:spring-context,aspectjrt,aspectjweaver。
1.编写一个切点Person:

public interface Person {
public String getName();
}

2.编写一个实现类SuperMan:

@Component("person")
public class SuperMan implements Person{
public String name;
public void setName(){
}
public String getName() {
return "i am superman";
}
}

3.编写一个切面Advice,使用@Aspect注解:

@Aspect
@Component
public class Advice {
@Before("execution(* com.kai.vo.Person.(..))")
public void methodbefore(){
System.out.println("methodbefore");
}
}

4.在配置文件上启用@EnableAspectJAutoProxy注解,启用自动代理。

@Configuration
@ComponentScan(basePackages={“com.kai.vo”,”com.kai.aspect”})
@PropertySource(“app.properties”)
@EnableAspectJAutoProxy
public class Configuration1 {
@Autowired
Environment env;

}

5.编写测试类:

public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
AnnotationConfigApplicationContext an=new AnnotationConfigApplicationContext("com.kai.config");
Person p=an.getBean("person",Person.class);
System.out.println(p.getName());
}
}

结果为:
Hello World!
methodbefore
i am superman
6.也可以单独配置切点,再引用切点:

@Aspect
@Component
public class Advice {
@Pointcut("execution(* com.kai.vo.Person.(..))")
public void person(){}
@Before("person()")
public void methodbefore(){
System.out.println("methodbefore");
}
}

切点配置说明:
1:execution():满足某一匹配模式的的所有目标类方法连接点
例如:

@Pointcut("execution(* com.kai.vo.Person.(..))")
public void person(){}

2:@annotation:定位到方法,标注了特定注解的目标方法连接点上
例如:

@Pointcut(“@annotation(com.kai.vo.Lazy)”)
public void person(){}

@Target({ElementType.CONSTRUCTOR,ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface Lazy {}</code>

3.args:定位于入参为特定类型的的方法,参数为包.类名比如:

@Component
public class Advice {
@Pointcut("args(String)")
public void person(){}
@Before("person()")
public void methodbefore(){
System.out.println("methodbefore");
}
}

同时注意若要将String name参数传递到通知中去,则要使用args(name),且不能单独定义切点,这样会根据name的String类型判断目标对象的方法的入参类型为String,如下:

@Aspect
@Component
public class Advice {
@Pointcut("args(name)")
public void person(){}
@Before("args(name)")
public void methodbefore(String name){
System.out.println("methodbefore"+name);
}
}

4.@args():定位于被特定注解的类作为方法入参的连接点
如:@args(com.kai.Lazy)
5.within(),细粒度在类级别
within(com.xyz.service.*)定位到包下所有类及其子类
within(com.xyz.service..*)定位到包及子包下所有类及其子类
within(com.kai.Person)定位到Person及其子类
this(com.xyz.service.Person)实现了Person接口的所有类
target(com.xyz.Person)实现Person接口的目标对象的任意连接点
this,target和定位到具体接口或类的within基本一样。
@target(org.springframework.transaction.annotation.Transactional)定位到类(不含子类), 目标对象中有一个 @Transactional 注解的任意连接点
@within(org.springframework.transaction.annotation.Transactional )定位到类及其子类,实际测试也只能定位到类,不能定位到子类。
任何一个目标对象声明的类型有一个 @Transactional 注解的连接点

@Lazy
public interface Person {
public String getName();
}

@Component
public class SuperMan implements Person{
public String name;
public void setName(){
}
public String getName() {
return “i am superman”;
}
}

@Aspect
@Component
public class Advice {
@Pointcut(“args(name)”)
public void person(){}
@Before(“@within(com.kai.vo.Lazy)”)
public void methodbefore(){
System.out.println(“methodbefore”);
}
}

public class App
{
public static void main( String[] args )
{
System.out.println( “Hello World!” );
AnnotationConfigApplicationContext an=new AnnotationConfigApplicationContext(“com.kai.config”);
Person p=an.getBean(“superMan”,Person.class);
System.out.println(p.getName());
}
}

结果为:
Hello World!
i am superman
并没有定位到子类。
参考文,章:http://blog.csdn.net/qwe6112071/article/details/50951720