Spring AOP教程(spring aop 一)

版权声明:随意转载。 https://blog.csdn.net/dengjili/article/details/83754691

jdk中的动态代理

  • 一个是原有类,一个是拦截器增强类
  • 通过代理类增强原有类的功能

在这里插入图片描述

代码实现

public interface RoleService {
	void print(Object obj);
}

public class RoleServiceImpl implements RoleService {
	@Override
	public void print(Object obj) {
		System.out.println("role 123");
		obj.toString();
	}
}

拦截器(增强类)

public interface Interceptor {
	void before(Object obj);
	void after(Object obj);
	void afterReturning(Object obj);
	void afterThrowing(Object obj);
}

public class RoleInterceptor implements Interceptor {
	@Override
	public void before(Object obj) {
		System.out.println("before");
	}

	@Override
	public void after(Object obj) {
		System.out.println("after");
	}

	@Override
	public void afterReturning(Object obj) {
		System.out.println("afterReturning");
	}

	@Override
	public void afterThrowing(Object obj) {
		System.out.println("afterThrowing");
	}
}

代理类

public class ProxyBeanFactory {
	public static <T> T getBean(T obj, Interceptor interceptor) {
		return (T) Proxy.newProxyInstance(ProxyBeanFactory.class.getClassLoader(), obj.getClass().getInterfaces(),
				new RoleInvocationHandler<>(obj, interceptor));
	}
}

public class RoleInvocationHandler<T> implements InvocationHandler {
	
	private T obj;
	private Interceptor intercept;
	
	public RoleInvocationHandler(T obj, Interceptor intercept) {
		this.obj = obj;
		this.intercept = intercept;
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		intercept.before(obj);
		Object invoke = null;
		try {
			invoke = method.invoke(obj, args);
			intercept.after(obj);
			intercept.afterReturning(obj);
		} catch (Exception e) {
			intercept.after(obj);
			intercept.afterThrowing(obj);
			e.printStackTrace();
		}
		
		return invoke;
	}

}

测试类

public class GameMain {
	public static void main(String[] args) {
		RoleService service = new RoleServiceImpl();
		Interceptor interceptor = new RoleInterceptor();
		RoleService proxy = ProxyBeanFactory.getBean(service, interceptor);
		proxy.print("x");
		System.out.println("=======================");
		proxy.print(null);
	}
}

运行结果

before
role 123
after
afterReturning
=======================
before
role 123
after
afterThrowing
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at priv.dengjl.spring.day3.game.invocation.RoleInvocationHandler.invoke(RoleInvocationHandler.java:22)
	at com.sun.proxy.$Proxy0.print(Unknown Source)
	at priv.dengjl.spring.day3.game.GameMain.main(GameMain.java:16)
Caused by: java.lang.NullPointerException
	at priv.dengjl.spring.day3.game.service.RoleServiceImpl.print(RoleServiceImpl.java:11)
	... 7 more

实现代理功能,以下为spring aop的演进

使用@AspectJ注解方式

maven引入包

<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.9.2</version>
		</dependency>

spring方式完成jdk中的动态代理

注解拦截器

@Aspect
public class RoleAspect {
	// temp方法,供其他方法使用
	@Pointcut("execution(* priv.dengjl.spring.day3.game.service.*.print(..))")
	public void pointcut(){}
	
	// 连接点
	@Before("pointcut()")
	public void before() {
		System.out.println("before() 正在运行!");
	}
	
	@After("pointcut()")
	public void after() {
		System.out.println("after() 正在运行!");
	}
	
	@AfterThrowing("pointcut()")
	public void afterThrowing() {
		System.out.println("afterThrowing() 正在运行!");
	}
	
	@AfterReturning("pointcut()")
	public void afterReturning() {
		System.out.println("afterReturning() 正在运行!");
	}
	
}

类增加@Component注解

@Component
public class RoleServiceImpl implements RoleService {
	@Override
	public void print(Object obj) {
		System.out.println("role 123");
		obj.toString();
	}
}

ioc入口配置

@Configuration
@ComponentScan(basePackages = {"priv.dengjl.spring.day3.game.service"})
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class AopConfig {
	
	@Bean
	public RoleAspect getRoleAspect() {
		return new RoleAspect();
	}
}

测试类

public class RunMain {

	public static void main(String[] args) {
		ApplicationContext ctx = new AnnotationConfigApplicationContext(AopConfig.class);
		RoleService service = ctx.getBean(RoleServiceImpl.class);
		
		service.print("");
		System.out.println("======");
		service.print(null);
	}
}

测试结果

before() 正在运行!
role 123
after() 正在运行!
afterReturning() 正在运行!
======
before() 正在运行!
role 123
after() 正在运行!
afterThrowing() 正在运行!
Exception in thread "main" java.lang.NullPointerException
	at priv.dengjl.spring.day3.game.service.RoleServiceImpl.print(RoleServiceImpl.java:11)
	at priv.dengjl.spring.day3.game.service.RoleServiceImpl$$FastClassBySpringCGLIB$$4feb7f53.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
	at priv.dengjl.spring.day3.game.service.RoleServiceImpl$$EnhancerBySpringCGLIB$$1998e232.print(<generated>)
	at priv.dengjl.spring.day3.game.test.RunMain.main(RunMain.java:19)

使用xml配置ioc入口

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<aop:aspectj-autoproxy proxy-target-class="true"/>
	<bean id="roleAspect" class="priv.dengjl.spring.day3.aspectj.RoleAspect"/>
	<bean id="roleServiceImpl" class="priv.dengjl.spring.day3.game.service.RoleServiceImpl"/>
	
</beans>

测试类

public class RunMain {
	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("aop.xml");
		RoleService service = ctx.getBean(RoleServiceImpl.class);
		
		service.print("");
		System.out.println("======");
		service.print(null);
	}
}

使AspectJ注解中环绕通知

拦截器

// 切面
@Aspect
public class RoleAroundAspect {
	// temp方法
	@Pointcut("execution(* priv.dengjl.spring.day3.game.service.*.print(..))")
	public void pointcut(){}
	
	// 连接点
	@Around("pointcut()  && args(obj)")
	public void testAround(ProceedingJoinPoint joinPoint, Object obj) throws Throwable {
		System.out.println(obj);
		System.out.println("前");
		try {
			joinPoint.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("后");
	}
	
}

ioc入口

@Configuration
@ComponentScan(basePackages = {"priv.dengjl.spring.day3.game.service"})
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class AopAroundConfig {
	
	@Bean
	public RoleAroundAspect getRoleAroundAspect() {
		return new RoleAroundAspect();
	}
}

测试类

public class RunMainAround {

	public static void main(String[] args) {
		ApplicationContext ctx = new AnnotationConfigApplicationContext(AopAroundConfig.class);
		RoleService service = ctx.getBean(RoleServiceImpl.class);
		
		service.print("12");
		System.out.println("======");
		service.print(null);

	}

}

测试结果

12
前
role 123
后
======
null
前
role 123
java.lang.NullPointerException
	at priv.dengjl.spring.day3.game.service.RoleServiceImpl.print(RoleServiceImpl.java:11)
	at priv.dengjl.spring.day3.game.service.RoleServiceImpl$$FastClassBySpringCGLIB$$4feb7f53.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
	at priv.dengjl.spring.day3.aspectj.RoleAroundAspect.testAround(RoleAroundAspect.java:21)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:174)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
	at priv.dengjl.spring.day3.game.service.RoleServiceImpl$$EnhancerBySpringCGLIB$$182bdc2f.print(<generated>)
	at priv.dengjl.spring.day3.game.test.RunMainAround.main(RunMainAround.java:18)
后

使用XMl配置方式实现

只是和注解实现不同,步骤一致

实现jdk中的代理

拦截器

// 切面
public class XmlAspect {
	
	// 连接点
	public void before() {
		System.out.println("before() 正在运行!");
	}
	
	public void after() {
		System.out.println("after() 正在运行!");
	}
	
	public void afterThrowing() {
		System.out.println("afterThrowing() 正在运行!");
	}
	
	public void afterReturning() {
		System.out.println("afterReturning() 正在运行!");
	}
	
}

配置xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<bean id="roleServiceImpl" class="priv.dengjl.spring.day3.game.service.RoleServiceImpl"/>
	<!-- 切面 -->
	<bean id="xmlAspect" class="priv.dengjl.spring.day3.aspectj.XmlAspect"/>
	
	<!-- aspect xml配置 -->
	<aop:config proxy-target-class="true">
		<!-- 切入点 -->
		<aop:pointcut expression="execution(* priv.dengjl.spring.day3.game.service.*.print(..))" id="rolePointcut"/>
		<!-- 连接切入点 -->
		<aop:aspect ref="xmlAspect">
			<aop:before method="before" pointcut-ref="rolePointcut"/>
			<aop:after method="after" pointcut-ref="rolePointcut"/>
			<aop:after-throwing method="afterThrowing" pointcut-ref="rolePointcut"/>
			<aop:after-returning method="afterReturning" pointcut-ref="rolePointcut"/>
		</aop:aspect>
	</aop:config>
	
</beans>

测试类

public class RunMainXml {

	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("aopXml.xml");
		RoleService service = ctx.getBean(RoleServiceImpl.class);
		
		service.print("");
		System.out.println("======");
		service.print(null);
	}

}

测试结果

Returning cached instance of singleton bean 'xmlAspect'
before() 正在运行!
role 123
Returning cached instance of singleton bean 'xmlAspect'
after() 正在运行!
Returning cached instance of singleton bean 'xmlAspect'
afterReturning() 正在运行!
======
Returning cached instance of singleton bean 'xmlAspect'
before() 正在运行!
role 123
Returning cached instance of singleton bean 'xmlAspect'
after() 正在运行!
Returning cached instance of singleton bean 'xmlAspect'
afterThrowing() 正在运行!
Exception in thread "main" java.lang.NullPointerException
	at priv.dengjl.spring.day3.game.service.RoleServiceImpl.print(RoleServiceImpl.java:11)
	at priv.dengjl.spring.day3.game.service.RoleServiceImpl$$FastClassBySpringCGLIB$$4feb7f53.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
	at priv.dengjl.spring.day3.game.service.RoleServiceImpl$$EnhancerBySpringCGLIB$$67b46357.print(<generated>)
	at priv.dengjl.spring.day3.game.test.RunMainXml.main(RunMainXml.java:17)

实现Around方式,并传入参数

拦截器

// 切面
public class XmlAroundAspect {
	
	public void around(ProceedingJoinPoint joinPoint, Object obj) throws Throwable {
		System.out.println(obj);
		System.out.println("前");
		try {
			joinPoint.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("后");
	}
	
}

xml配置文件

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<bean id="roleServiceImpl" class="priv.dengjl.spring.day3.game.service.RoleServiceImpl"/>
	<!-- 切面 -->
	<bean id="xmlAspect" class="priv.dengjl.spring.day3.aspectj.XmlAroundAspect"/>
	
	<!-- aspect xml配置 -->
	<aop:config proxy-target-class="true">
		<!-- 连接切入点 -->
		<aop:aspect ref="xmlAspect">
			<aop:around method="around" pointcut="execution(* priv.dengjl.spring.day3.game.service.*.print(..)) and args(obj)" />
		</aop:aspect>
	</aop:config>
	
</beans>

测试类

public class RunMainXmlAround {

	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("aopAroundXml.xml");
		RoleService service = ctx.getBean(RoleServiceImpl.class);
		
		service.print("12");
		System.out.println("======");
		service.print(null);

	}

}

多个拦截器

在这里插入图片描述

引入@Order注解,使得程序有序

原类

public interface MutiBean {
	void test();
}

@Component
public class MutiBeanImpl implements MutiBean {

	@Override
	public void test() {
		System.out.println("MutiBeanImpl");
	}

}

拦截器1

// 切面
@Aspect
@Order(3)
public class Aspect1 {
	// temp方法
	@Pointcut("execution(* priv.dengjl.spring.day4.*.test(..))")
	public void pointcut(){}
	
	// 连接点
	@Before("pointcut()")
	public void before() {
		System.out.println("before1() 正在运行!");
	}
	
	@After("pointcut()")
	public void after() {
		System.out.println("after1() 正在运行!");
	}
	
	@AfterThrowing("pointcut()")
	public void afterThrowing() {
		System.out.println("afterThrowing1() 正在运行!");
	}
	
	@AfterReturning("pointcut()")
	public void afterReturning() {
		System.out.println("afterReturning1() 正在运行!");
	}
	
}

拦截器2

// 切面
@Aspect
@Order(2)
public class Aspect2 {
	// temp方法
	@Pointcut("execution(* priv.dengjl.spring.day4.*.test(..))")
	public void pointcut(){}
	
	// 连接点
	@Before("pointcut()")
	public void before() {
		System.out.println("before2() 正在运行!");
	}
	
	@After("pointcut()")
	public void after() {
		System.out.println("after2() 正在运行!");
	}
	
	@AfterThrowing("pointcut()")
	public void afterThrowing() {
		System.out.println("afterThrowing2() 正在运行!");
	}
	
	@AfterReturning("pointcut()")
	public void afterReturning() {
		System.out.println("afterReturning2() 正在运行!");
	}
	
}

拦截器3

// 切面
@Aspect
@Order(1)
public class Aspect3 {
	// temp方法
	@Pointcut("execution(* priv.dengjl.spring.day4.*.test(..))")
	public void pointcut(){}
	
	// 连接点
	@Before("pointcut()")
	public void before() {
		System.out.println("before3() 正在运行!");
	}
	
	@After("pointcut()")
	public void after() {
		System.out.println("after3() 正在运行!");
	}
	
	@AfterThrowing("pointcut()")
	public void afterThrowing() {
		System.out.println("afterThrowing3() 正在运行!");
	}
	
	@AfterReturning("pointcut()")
	public void afterReturning() {
		System.out.println("afterReturning3() 正在运行!");
	}
	
}

ioc入口

@Configuration
@ComponentScan(basePackages = {"priv.dengjl.spring.day4"})
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class AopConfig {
	
	@Bean
	public Aspect1 getAspect1() {
		return new Aspect1();
	}
	@Bean
	public Aspect2 getAspect2() {
		return new Aspect2();
	}
	@Bean
	public Aspect3 getAspect3() {
		return new Aspect3();
	}
}

测试类

public class RunMain {

	public static void main(String[] args) {
		ApplicationContext ctx = new AnnotationConfigApplicationContext(AopConfig.class);
		MutiBean service = ctx.getBean(MutiBeanImpl.class);
		
		service.test();
	}
}

测试结果

Returning cached instance of singleton bean 'mutiBeanImpl'
Returning cached instance of singleton bean 'getAspect3'
before3() 正在运行!
Returning cached instance of singleton bean 'getAspect2'
before2() 正在运行!
Returning cached instance of singleton bean 'getAspect1'
before1() 正在运行!
MutiBeanImpl
after1() 正在运行!
afterReturning1() 正在运行!
after2() 正在运行!
afterReturning2() 正在运行!
after3() 正在运行!
afterReturning3() 正在运行!

猜你喜欢

转载自blog.csdn.net/dengjili/article/details/83754691
今日推荐