1、execution方式:
execution 表达式里面参数说明如下图:图内有【1】【2】【3】【4】位置一一对应的。
execution(public * *(..)) // public[1]、*[2]、*[3]、(..)[4]
(1)【1】位置 public 拦截方法的权限符(private、protected都可以),如果任何权限都可以,不写 * 作为通配符(应该省略【1】位置什么都不写)。
(2) 【2】位置的通配符 * 指方法返回值 例如(void、String)
(3). 【3】位置的通配符 * 指 包路径下指定的接口、包路径下的所有子类(*是以 包路径、类名或接口名、方法名组成)
(4) 【4】位置的通配符 (…) 指 方法入参请求的类型 例如(java.Lang.Integer、java.Lang.String)
execution方式的demo:
demo创建截图:
创建接口DaoExecution:
public interface DaoExecution {
Integer method1(Integer i);
String method2(String str);
}
创建DaoExecutionIndex1类,方法method1、method2
package com.it.app.aspectj.execution;
import org.springframework.stereotype.Component;
@Component(value = "daoExecutionIndex1")
public class DaoExecutionIndex1 implements DaoExecution{
@Override
public Integer method1(Integer i) {
return i;
}
@Override
public String method2(String str) {
return str;
}
}
创建扫描类 Appconfig 开启 @EnableAspectJAutoProxy 通过注解:
package com.it.app.aspectj.scan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@ComponentScan("com.it.app.aspectj.execution")
@EnableAspectJAutoProxy
public class Appconfig {
}
创建切面和切点ExecutionAspect:
package com.it.app.aspectj.execution;
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 ExecutionAspect {
@Pointcut("execution(public Integer com.it.app.aspectj.execution.DaoExecutionIndex1.method1*(java.lang.Integer,..))")
public void interceptAspectjExecution() {
}
@Before("interceptAspectjExecution()")
public void ExecutionRun(){
System.out.println("before : execution拦截方法");
}
}
执行method1、method2只拦截了method1:
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
DaoExecution daoExecution = (DaoExecution)context.getBean("daoExecutionIndex1");
System.out.println(daoExecution.method1(1));
System.out.println(daoExecution.method2("2"));
}
}
结果截图只执行method1的方法:
before : execution拦截方法
1
2
2、within方式:
修改 ExecutionAspect 切面和切点
package com.it.app.aspectj.execution;
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 ExecutionAspect {
@Pointcut("within( com.it.app.aspectj.execution..*)")
public void interceptAspectjWithin() {
}
@Before("interceptAspectjWithin()")
public void withinRun(){
System.out.println("before : within拦截方法");
}
}
执行结果将 method1、method2全部拦截
package com.it.app.aspectj;
import com.it.app.aspectj.execution.DaoExecution;
import com.it.app.aspectj.scan.Appconfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
DaoExecution daoExecution = (DaoExecution)context.getBean("daoExecutionIndex1");
System.out.println(daoExecution.method1(1));
System.out.println(daoExecution.method2("2"));
}
}
执行结果
before : within拦截方法
1
before : within拦截方法
2
3、target方式与this:
this 和 target 对比分四种情况
(1)开启jdk动态代理、拦截相同接口
(2)开启jdk动态代理、拦截相同接口实现类
(3)开启CGLIB代理、拦截相同接口
(4)开启jCGLIB代理、拦截相同接口实现类
demo如下:
默认开启 jdk动态代理 、 true开启CGLIB代理,修改直接修改下面proxyTargetClass=false为true。
@ComponentScan("com.it.app.aspectj.execution")
//默认开启 jdk动态代理 、 true开启CGLIB代理
@EnableAspectJAutoProxy(proxyTargetClass=false)
public class Appconfig {
}
(ExecutionAspect)切面和切点拦截DaoExecution接口,
如果要变更this表达式为target则将this替换成target
如果要拦截DaoExecution的实现类,则替换为com.it.app.aspectj.execution.DaoExecutionIndex1
@Aspect
@Component
public class ExecutionAspect {
//将this替换成target
//如果要拦截DaoExecution的实现类,则替换为com.it.app.aspectj.execution.DaoExecutionIndex1
@Pointcut("this(com.it.app.aspectj.execution.DaoExecution)")
public void interceptAspectjThis() {
}
@Before("interceptAspectjThis()")
public void thisRun(){
System.out.println("before : this拦截方法");
}
}
启动类
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
DaoExecution daoExecution1 = (DaoExecution)context.getBean("daoExecutionIndex1");
//生成代理类proxy与DaoExecutionIndex1不是一个对象
System.out.println("生成代理类proxy与DaoExecutionIndex1不是一个对象:"+(daoExecution1 instanceof DaoExecutionIndex1));
System.out.println(daoExecution1.method1(1));
System.out.println(daoExecution1.method2("2"));
}
}
四种情况拦截数据情况:
(1) this 和 target动态代理 拦截接口:
生成代理类proxy与DaoExecutionIndex1不是一个对象:false
before : this拦截方法
1
before : this拦截方法
2
生成代理类proxy与DaoExecutionIndex1不是一个对象:false
before : this拦截方法
1
before : this拦截方法
2
执行结果两者相同
(2) this 和 target动态代理 拦截接口实现类:
生成代理类proxy与DaoExecutionIndex1不是一个对象:false
1
2
生成代理类proxy与DaoExecutionIndex1不是一个对象:false
before : this拦截方法
1
before : this拦截方法
2
只有target被拦截了
(3)开启CGLIB代理、拦截相同接口
生成代理类proxy与DaoExecutionIndex1不是一个对象:true
before : this拦截方法
1
before : this拦截方法
2
生成代理类proxy与DaoExecutionIndex1不是一个对象:true
before : this拦截方法
1
before : this拦截方法
2
this与target相同被拦截
(4)开启jCGLIB代理、拦截相同接口实现类
生成代理类proxy与DaoExecutionIndex1不是一个对象:true
before : this拦截方法
1
before : this拦截方法
2
生成代理类proxy与DaoExecutionIndex1不是一个对象:true
before : this拦截方法
1
before : this拦截方法
2
两者都被拦截
4、args拦截方法参数(按照类型匹配):
demo:
@Aspect
@Component
public class ExecutionAspect {
@Pointcut("args(java.lang.String)")
public void interceptAspectjAgrs() {
}
@Before("interceptAspectjAgrs()")
public void thisRun(){
System.out.println("before : agrs拦截方法");
}
}
执行结果:
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
DaoExecution daoExecution1 = (DaoExecution)context.getBean("daoExecutionIndex1");
//生成代理类proxy与DaoExecutionIndex1不是一个对象
// System.out.println("生成代理类proxy与DaoExecutionIndex1不是一个对象:"+(daoExecution1 instanceof DaoExecutionIndex1));
System.out.println(daoExecution1.method1(1));
System.out.println(daoExecution1.method2("2"));
}
}
1
before : agrs拦截方法
2
只拦截了method2参数类型为String的。
4、@annotation通过注解去拦截:
自定义注解:
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationDemo {
}
切面和切点拦截配置:
@Aspect
@Component
public class ExecutionAspect {
//注解包路径 @Pointcut("@annotation(com.it.app.aspectj.execution.AnnotationDemo)")
public void interceptAspectjAnnotation() {
}
@Before("interceptAspectjAnnotation()")
public void thisRun(){
System.out.println("before : Annotation拦截方法");
}
}
在method1方法上添加注解
@Component(value = "daoExecutionIndex1")
public class DaoExecutionIndex1 implements DaoExecution{
@Override
@AnnotationDemo
public Integer method1(Integer i) {
return i;
}
@Override
public String method2(String str) {
return str;
}
}
执行结果:
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
DaoExecution daoExecution1 = (DaoExecution)context.getBean("daoExecutionIndex1");
//生成代理类proxy与DaoExecutionIndex1不是一个对象
// System.out.println("生成代理类proxy与DaoExecutionIndex1不是一个对象:"+(daoExecution1 instanceof DaoExecutionIndex1));
System.out.println(daoExecution1.method1(1));
System.out.println(daoExecution1.method2("2"));
}
}
只拦截在方法上添加注解的方法
before : Annotation拦截方法
1
2
5、@within和t@arget通过注解去拦截:
创建DaoExecutionIndexZ1类继承DaoExecutionIndex1,将注解@AnnotationDemo添加到DaoExecutionIndex1上。
@Component(value = "daoExecutionIndex1")
@AnnotationDemo
public class DaoExecutionIndex1 implements DaoExecution{
@Override
public Integer method1(Integer i) {
return i;
}
@Override
public String method2(String str) {
return str;
}
}
@Component
public class DaoExecutionIndexZ1 extends DaoExecutionIndex1{
public Integer method3(Integer i) {
return i;
}
}
开启cglib代理
@ComponentScan("com.it.app.aspectj.execution")
//默认开启 jdk动态代理 、 true开启CGLIB代理
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class Appconfig {
}
注解替换只需要把@target替换成@within
package com.it.app.aspectj.execution;
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 ExecutionAspect {
@Pointcut("@target(com.it.app.aspectj.execution.AnnotationDemo)")
public void interceptAspectjAnnotation() {
}
@Before("interceptAspectjAnnotation()")
public void thisRun(){
System.out.println("before : Annotation拦截方法");
}
}
执行结果:
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
DaoExecution daoExecution1 = (DaoExecution)context.getBean("daoExecutionIndex1");
//生成代理类proxy与DaoExecutionIndex1不是一个对象
// System.out.println("生成代理类proxy与DaoExecutionIndex1不是一个对象:"+(daoExecution1 instanceof DaoExecutionIndex1));
System.out.println(daoExecution1.method1(1));
System.out.println(daoExecution1.method2("2"));
DaoExecutionIndexZ1 daoExecution3 = (DaoExecutionIndexZ1)context.getBean("daoExecutionIndexZ1");
System.out.println(daoExecution3.method3(4));
}
}
before : Annotation拦截方法
1
before : Annotation拦截方法
2
4
@within和@target执行结果一样,拦截类的方法(但@within可以拦截子类未重写方法,未拦截)。
6、@args作用是拦截方法参数:
自定义个user类,添加注解@AnnotationDemo
@AnnotationDemo
public class User {
private String name;
public String getName() {
return name;
}
public User(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
}
添加方法method5的传入参数为user(添加接口方法)
@Component(value = "daoExecutionIndex1")
public class DaoExecutionIndex1 implements DaoExecution{
@Override
public Integer method1(Integer i) {
return i;
}
@Override
public String method2(String str) {
return str;
}
public String method5(User user){
return user.getName();
}
}
表达式拦截
@Pointcut("@args(com.it.app.aspectj.execution.AnnotationDemo)")
public void interceptAspectjAnnotation() {
}
@Before("interceptAspectjAnnotation()")
public void thisRun(){
System.out.println("before : @args拦截方法");
}
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
DaoExecution daoExecution1 = (DaoExecution)context.getBean("daoExecutionIndex1");
//生成代理类proxy与DaoExecutionIndex1不是一个对象
// System.out.println("生成代理类proxy与DaoExecutionIndex1不是一个对象:"+(daoExecution1 instanceof DaoExecutionIndex1));
System.out.println(daoExecution1.method1(1));
System.out.println(daoExecution1.method2("2"));
User user = new User("dz");
System.out.println(daoExecution1.method5(user));
}
}
结果拦截成功method5
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
DaoExecution daoExecution1 = (DaoExecution)context.getBean("daoExecutionIndex1");
//生成代理类proxy与DaoExecutionIndex1不是一个对象
// System.out.println("生成代理类proxy与DaoExecutionIndex1不是一个对象:"+(daoExecution1 instanceof DaoExecutionIndex1));
System.out.println(daoExecution1.method1(1));
System.out.println(daoExecution1.method2("2"));
User user = new User("dz");
System.out.println(daoExecution1.method5(user));
}
}