SpringAOP详解(上)

当需要在方法前后做一些操作就需要借助动态代理来实现

一、动态代理实现方法

1、jdk自带实现方式

jdk实现代理是被代理类实现接口的方式

public interface UserInterface {

	void test();
}

public class UserService implements UserInterface {

	public void test() {
		System.out.println("call test method");
	}

}


UserService target = new UserService();

		Object o = Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[]{UserInterface.class}, new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				System.out.println("test method before");
				Object invoke = method.invoke(target, args);
				System.out.println("test method after");
				return invoke;
			}
		});
		// 只能代理实现UserInterface接口的类,不能强转成UserService
		UserInterface userInterface = (UserInterface)o;
		userInterface.test();

打印结果:

test method before
call test method
test method after 

必须基于实现接口,产生代理对象类型是UserInterface,而不是UserService

2、基于cglib实现

相比jdk动态代理,cglib不需要修改代码就可以实现动态代理,cglib实现代理是继承被代理类的方式

public class UserService {
	public void test() {
		System.out.println("call test method");
	}

	public void a() {
		System.out.println("call test a");
	}
}

UserService target = new UserService();

		// 通过cglib技术
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(UserService.class);

		// 定义额外逻辑,也就是代理逻辑
		enhancer.setCallbacks(new Callback[]{new MethodInterceptor() {
			@Override
			public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
				System.out.println("before...");
				Object result = methodProxy.invoke(target, objects);
				System.out.println("after...");
				return result;
			}
		}, NoOp.INSTANCE});
		enhancer.setCallbackFilter(new CallbackFilter() {
			@Override
			public int accept(Method method) {
				if (method.getName().equals("test")) {
					return 0;
				} else {
					return 1;
				}
			}
		});

		// 动态代理所创建出来的UserService对象
		UserService userService = (UserService) enhancer.create();
		// 执行这个userService的test方法时,就会额外会执行一些其他逻辑
		userService.test();
		// 调用a方法时对应过滤返回的是1,NoOp.INSTANCE是空操作,不会对代理对象做任何操作
		userService.a();

打印结果:

before...
call test method
after...
call test a

3、spring对jdk和cglib进行封装的ProxyFactory

public class UserService {
	public void test() {
		System.out.println("call test method");
	}
}

UserService target = new UserService();

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.setTarget(target);
//		proxyFactory.setInterfaces(UserInterface.class); // jdk动态时设置
		proxyFactory.addAdvice(new MethodInterceptor() {
			@Override
			public Object invoke(MethodInvocation invocation) throws Throwable {
				System.out.println("before...");
				Object result = invocation.proceed();
				System.out.println("after...");
				return result;
			}
		});

		UserService userService = (UserService) proxyFactory.getProxy();
		userService.test();

打印结果:

before...
call test method
after...

4、Advice分类

  1. Before Advice:方法之前执行
  2. After returning advice:方法return后执行
  3. After throwing advice:方法抛异常后执行
  4. After (finally) advice:方法执行完finally之后执行,这是最后的,比return更后
  5. Around advice:这是功能最强大的Advice,可以自定义执行顺序
Before Advice
ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.setTarget(target);
//		proxyFactory.setInterfaces(UserInterface.class); // jdk动态时设置
		proxyFactory.addAdvice(new TestBeforeAdvice());

		UserService userService = (UserService) proxyFactory.getProxy();
		userService.test();

public class TestBeforeAdvice implements MethodBeforeAdvice {
	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("方法执行之前");
	}
}

public class UserService {
	public void test() {
		System.out.println("call test method");
	}
}

打印结果:

方法执行之前
call test method 

After returning advice
ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.setTarget(target);
//		proxyFactory.setInterfaces(UserInterface.class); // jdk动态时设置
		proxyFactory.addAdvice(new TestAfterReturningAdvice());

		UserService userService = (UserService) proxyFactory.getProxy();
		userService.test();

public class TestAfterReturningAdvice implements AfterReturningAdvice {
	@Override
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		System.out.println("方法返回之后");
	}
}

public class UserService {
	public void test() {
		System.out.println("call test method");
	}
}

打印结果:

call test method
方法返回之后 

After throwing advice

可根据异常类型在指定异常发生时做对应操作

ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.setTarget(target);
//		proxyFactory.setInterfaces(UserInterface.class); // jdk动态时设置
		proxyFactory.addAdvice(new TestAfterThrowingAdvice());

		UserService userService = (UserService) proxyFactory.getProxy();
		userService.test();

public class TestAfterThrowingAdvice implements ThrowsAdvice {

	public void afterThrowing(Method method, Object[] args, Object target, Exception ex) {
		System.out.println("方法执行发生异常");
	}
}

public class UserService {
	public void test() {
		System.out.println("call test method");
		throw new RuntimeException();
	}
}

打印结果:

call test method
方法执行发生异常
Exception in thread "main" java.lang.RuntimeException
	at com.zhouyu.service.UserService.test(UserService.java:25)
	at com.zhouyu.service.UserService$$FastClassBySpringCGLIB$$7bfcfe0.invoke()
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:791)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
	at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:113)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:198)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:704)
	at com.zhouyu.service.UserService$$EnhancerBySpringCGLIB$$e9a0fc71.test()
	at com.zhouyu.Test.main(Test.java:25)
Around advice:
UserService target = new UserService();

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.setTarget(target);
//		proxyFactory.setInterfaces(UserInterface.class); // jdk动态时设置
		proxyFactory.addAdvice(new TestAroundAdvice());

		UserService userService = (UserService) proxyFactory.getProxy();
		userService.test();

public class UserService {
	public void test() {
		System.out.println("call test method");
	}
}

public class TestAroundAdvice implements MethodInterceptor {
	@Nullable
	@Override
	public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
		System.out.println("方法执行之前");
		Object proceed = invocation.proceed();
		System.out.println("方法执行之后");
		return proceed;
	}
}

打印结果:

方法执行之前
call test method
方法执行之后

上述的Advice只要是UserService类的方法都会被代理执行

5、Advisor

添加自己想执行的执行的方法,下面代码只会执行test方法的Advice代码

public class UserService {
	public void test() {
		System.out.println("call test method");
	}

	public void a() {
		System.out.println("call test a");
	}
}

UserService target = new UserService();

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.setTarget(target);
//		proxyFactory.setInterfaces(UserInterface.class); // jdk动态时设置
//		proxyFactory.addAdvice(new TestBeforeAdvice());
		proxyFactory.addAdvisor(new PointcutAdvisor() {
			@Override
			public Pointcut getPointcut() {
				return new StaticMethodMatcherPointcut() {
					@Override
					public boolean matches(Method method, Class targetClass) {
						if (method.getName().equals("test")) {
							return true;
						}
						return false;
					}
				};
			}

			@Override
			public Advice getAdvice() {
				return new TestBeforeAdvice();
			}

			@Override
			public boolean isPerInstance() {
				return false;
			}
		});

		UserService userService = (UserService) proxyFactory.getProxy();
		userService.test();
		userService.a();

打印结果:

方法执行之前
call test method
call test a

二、ProxyFactoryBean

利用ProxyFactoryBean生成一个代理对象,执行test方法之前执行代理逻辑

public class UserService {
	public void test() {
		System.out.println("call test method");
	}

	public void a() {
		System.out.println("call test a");
	}
}

@Bean
	public ProxyFactoryBean userServiceProxy() {
		ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
		proxyFactoryBean.setTarget(new UserService());
		proxyFactoryBean.addAdvice(new TestBeforeAdvice());
		return proxyFactoryBean;
	}


AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		UserService userService = (UserService) applicationContext.getBean("userServiceProxy");
		userService.test();

打印结果:

方法执行之前
call test method 

三、BeanNameAutoProxyCreator

beanName匹配到的将会自动创建代理对象,根据设置的Advice在调用方法时执行相关代理逻辑(通过beanPostProcessor把Advice添加到一个集合中,当调用调用被代理类时,指定的beanName的方法执行时都会执行代理逻辑)

@Bean
	public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
		BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
		beanNameAutoProxyCreator.setBeanNames("userSe*");
		beanNameAutoProxyCreator.setInterceptorNames("testBeforeAdvice");
		beanNameAutoProxyCreator.setProxyTargetClass(true);

		return beanNameAutoProxyCreator;
	}

@Component
public class TestBeforeAdvice implements MethodBeforeAdvice {
	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("方法执行之前");
	}
}

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		UserService userService = (UserService) applicationContext.getBean("userService");
		userService.test();

打印结果:

方法执行之前
call test method

四、DefaultAdvisorAutoProxyCreator

// 定义一个advisor
	@Bean
	public DefaultPointcutAdvisor defaultPointcutAdvisor(){
		NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
		pointcut.addMethodName("test");

		DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
		defaultPointcutAdvisor.setPointcut(pointcut);
		defaultPointcutAdvisor.setAdvice(new TestBeforeAdvice());
		
		return defaultPointcutAdvisor;
	}

	// 执行beanPostProcessor时会把advisor添加到一个集合中
	@Bean
	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
		return defaultAdvisorAutoProxyCreator;
	}

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		UserService userService = (UserService) applicationContext.getBean("userService");
		userService.test();

打印结果:

方法执行之前
call test method

五、AOP概念

AspectJ是在编译时对字节码进行了修改,是直接在UserService类对应的字节码中进行增强的,也就是可以理解为是在编译时就会去解析@Before这些注解,然后得到代理逻辑,加入到被代理的类中的字节码中去的,所以如果想用AspectJ技术来生成代理对象 ,是需要用单独的AspectJ编译器的。我们在项目中很少这么用,我们仅仅只是用了@Before这些注解,而我们在启动Spring的过程中,Spring会去解析这些注解,然后利用动态代理机制生成代理对象的。

  1. Aspect:表示切面,比如被@Aspect注解的类就是切面,可以在切面中去定义Pointcut、Advice等等
  2. Join point:表示连接点,表示一个程序在执行过程中的一个点,比如一个方法的执行,比如一个异常的处理,在Spring AOP中,一个连接点通常表示一个方法的执行。
  3. Advice:表示通知,表示在一个特定连接点上所采取的动作。Advice分为不同的类型,后面详细讨论,在很多AOP框架中,包括Spring,会用Interceptor拦截器来实现Advice,并且在连接点周围维护一个Interceptor链
  4. Pointcut:表示切点,用来匹配一个或多个连接点,Advice与切点表达式是关联在一起的,Advice将会执行在和切点表达式所匹配的连接点上
  5. Introduction:可以使用@DeclareParents来给所匹配的类添加一个接口,并指定一个默认实现
  6. Target object:目标对象,被代理对象
  7. AOP proxy:表示代理工厂,用来创建代理对象的,在Spring Framework中,要么是JDK动态代理,要么是CGLIB代理
  8. Weaving:表示织入,表示创建代理对象的动作,这个动作可以发生在编译时期(比如Aspejctj),或者运行时,比如Spring AOP

​AspectJ定义的几个注解

  1. @Before
  2. @AfterReturning
  3. @AfterThrowing
  4. @After
  5. @Around

你可能感兴趣的:(spring,java,开发语言)