1. 程式人生 > >spring整理(三)Spring AOP

spring整理(三)Spring AOP

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的預設選擇,必須依賴介面

    程式碼


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,讀者可對其進一步封裝,

  1. 掃描配置類

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();
	}

}


  1. 攔截器

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();
		}
	}
}