spring整理(三)Spring AOP
阿新 • • 發佈:2018-12-05
Spring AOP
AOP作為Spring中一個核心模組,通過代理模式在程式中架起了一層可自定義的攔截器
代理模式原理
-
靜態代理
一個靜態代理只能代理一個介面下的所有實現類
程式碼
/**
* 一個靜態代理只能代理一個介面下的所有實現類
*/
public class GreetingProxyStatic implements Greeting{
private GreetingImpl greetingImpl;
public GreetingProxyStatic (GreetingImpl greetingImpl) {
super();
this.greetingImpl = greetingImpl;
}
@Override
public void sayHello(String name) {
before();
greetingImpl.sayHello(name);
after();
}
private void before() {
System.out.println("before");
}
private void after() {
System.out.println("before");
}
}
class GreetingImpl implements Greeting{
@Override
public void sayHello(String name) {
System.out.println("name");
}
}
interface Greeting {
void sayHello(String name);
}
class Client {
public static void main(String[] args) {
Greeting greetingProxyStatic = new GreetingProxyStatic( new GreetingImpl());
greetingProxyStatic.sayHello("name");
}
}
-
動態代理
一個動態代理可代理多個介面下的實現類,可通過配置proxy-target-class(false為JDK,true為CGlib)去切換- jdk代理
jdk代理是Spring的預設選擇,必須依賴介面
程式碼
- jdk代理
package com.td.mode;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 被代理的Class必須實現介面
* spring預設使用JDK動態代理
*/
public class GreetingProxyDynamicJDK implements InvocationHandler{
private Object target;
public GreetingProxyDynamicJDK(Object target) {
super();
this.target = target;
}
@SuppressWarnings("unchecked")
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(target, args);
after();
return result;
}
private void before() {
System.out.println("before");
}
private void after() {
System.out.println("before");
}
}
class GreetingImpl implements Greeting{
@Override
public void sayHello(String name) {
System.out.println("name");
}
}
interface Greeting {
void sayHello(String name);
}
class Client {
public static void main(String[] args) {
Greeting greetingProxyDynamicJDK = new GreetingProxyDynamicJDK(new GreetingImpl()).getProxy();
greetingProxyDynamicJDK.sayHello("name");
}
}
- cglib代理
jdk代理是Spring的預設選擇,可直接代理任何類
程式碼
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
/**
* 直接代理Class,被代理的Class不需要實現介面
* spring-boot預設使用CGlib動態代理
*/
public class GreetingProxyDynamicCGlib implements MethodInterceptor{
public static final GreetingProxyDynamicCGlib instance = new GreetingProxyDynamicCGlib();
private GreetingProxyDynamicCGlib() {}
@SuppressWarnings("unchecked")
public <T> T getProxy(Class<T> cls) {
return (T) Enhancer.create(cls, this);
}
@Override
public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {
before();
Object result = proxy.invokeSuper(target, args);
after();
return result;
}
private void before() {
System.out.println("before");
}
private void after() {
System.out.println("before");
}
}
class GreetingImpl implements Greeting{
@Override
public void sayHello(String name) {
System.out.println("name");
}
}
interface Greeting {
void sayHello(String name);
}
class Client {
public static void main(String[] args) {
Greeting greetingProxyDynamicCGlib = GreetingProxyDynamicCGlib.instance.getProxy(GreetingImpl.class);
greetingProxyDynamicCGlib.sayHello("name");
}
}
Spring AOP使用
直接上程式碼,筆者為了簡單易讀只寫個Demo,讀者可對其進一步封裝,
- 掃描配置類
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import com.zgg.group2.rest.aspect.pojo.AspectDemo;
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass=false)
@ComponentScan(basePackages="com.zgg.group2")
public class AspectConfig {
@Bean
public AspectDemo aspectDemo() {
return new AspectDemo();
}
}
- 攔截器
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.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import com.zgg.group2.rest.bean.ZgUser;
@Aspect
@Component
public class AspectDemo {
//execution(任意返回值 url.任意類名(任意方法名))
// @execution(* com.zgg.group2.rest.impl.*.save*(..))
@Pointcut("execution(* com.zgg.group2.rest.impl.*.*(com.zgg.group2.rest.bean.ZgUser)) "
+ "&& args(zgUser)")
public void pointcutProxy(ZgUser zgUser){};
@Before("pointcutProxy(zgUser)")
public void before1(ZgUser zgUser) {
System.out.println("execute method before1 and name = "+zgUser.getName());
}
@Before("pointcutProxy(zgUser)")
public void before2(ZgUser zgUser) {
System.out.println("execute method before2 and name = "+zgUser.getName());
}
@AfterReturning("pointcutProxy(zgUser)")
public void afterReturning(ZgUser zgUser) {
System.out.println("execute method afterReturning and name = "+zgUser.getName());
}
@AfterThrowing("pointcutProxy(zgUser)")
public void afterThrowing(ZgUser zgUser) {
System.out.println("execute method afterThrowing and name = "+zgUser.getName());
}
@Around("pointcutProxy(zgUser)")
public void around(ProceedingJoinPoint jp, ZgUser zgUser) {
try {
System.out.println("around before and name = "+zgUser.getName());
jp.proceed();
System.out.println("around after");
} catch (Throwable e) {
e.printStackTrace();
}
}
}