spring的AOP--面向切面编程


AOP概念


1、AOP:aspect oriented programming 面向切面编程


2、AOP在spring中的作用

     提供声明式服务(声明式事务)

     允许用户实现自定义切面


3、AOP:在不改变原有代码的情况下,增加新的功能。


4、名词解释:

关注点:增加的某个业务。如日志、安全、缓存、事务、异常处理等。

        切   面 :一个关注点的模块化。

连接点:表示一个方法的执行。

通   知 :在切面的某个特定的连接点上执行的动作。

目标对象:被代理的对象--真实对象。

织   入 :把切面连接到其他的应用程序类型或者对象上,并创建一个被通知的对象。


5、使用spring实现aop


第一种实现方式: 通过spring的api来实现



前置通知


项目结构如下:




查看spring中文帮助文档,文档下载地址:《spring中文帮助文档.chm


中有关于aop通知的介绍,我们现在使用前置通知,从文档中可以知道我们要实现MethodBeforeAdvice,如下图:




Log代码:


package cn.myspring.log;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

/**
 * 日志切面
 */
public class Log implements MethodBeforeAdvice {

	/**
	 * @param method
	 *            :被调用的方法对象
	 * @param args
	 *            : 被调用的方法的参数
	 * @param target
	 *            : 被调用方法的目标对象
	 */
	@Override
	public void before(Method method, Object[] args, Object target)
			throws Throwable {
		System.out.println(target.getClass().getName() + "的" + method.getName()
				+ " 方法被执行");
	}
}


UserService代码:


package cn.myspring.service;

/**
 * 抽象角色
 */
public interface UserService {

	public void add() ;
	public void update() ;
	public void delete() ;
	public void search() ;
}


UserServiceImpl代码:


package cn.myspring.service;

/**
 * 真实角色
 */
public class UserServiceImpl implements UserService {

	@Override
	public void add() {
		System.out.println("增加用户");
	}

	@Override
	public void update() {
		System.out.println("修改用户");
	}

	@Override
	public void delete() {
		System.out.println("删除用户");
	}

	@Override
	public void search() {
		System.out.println("查询用户");
	}
	
}


beans.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.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
   
	<bean id="userService" class="cn.myspring.service.UserServiceImpl"></bean>
	<bean id="log" class="cn.myspring.log.Log"></bean>
	<aop:config>
		<!-- aop:pointcut切入点配置:
			execution() : 是表达式; 
			*  : 表示所有返回值 ;
			位置 : cn.myspring.service.UserServiceImpl ;
			方法 : add() ;
		-->
		<aop:pointcut expression="execution(* cn.myspring.service.UserServiceImpl.add())" id="pointcut"/>
		<!-- aop:advisor : 告诉程序,切入点如嵌入的业务有哪些;
			 advice-ref  : 对应的公共业务 ;
			 pointcut-ref: 切入点。
		 -->
		<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
	</aop:config>
</beans>


Test类代码:


package com.myspring.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.myspring.service.UserService;

public class Test {

	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml") ;
		UserService userService = (UserService) ac.getBean("userService") ;
		userService.add() ;
	}
	
}

运行Test类,控制台打印信息:


2017-8-16 10:04:28 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2747ee05: startup date [Wed Aug 16 10:04:28 CST 2017]; root of context hierarchy
2017-8-16 10:04:29 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans.xml]
2017-8-16 10:04:29 org.springframework.context.support.ClassPathXmlApplicationContext refresh
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService' defined in class path resource [beans.xml]: BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0': Cannot resolve reference to bean 'pointcut' while setting bean property 'pointcut'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pointcut': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.aop.aspectj.AspectJExpressionPointcut]: No default constructor found; nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService' defined in class path resource [beans.xml]: BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0': Cannot resolve reference to bean 'pointcut' while setting bean property 'pointcut'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pointcut': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.aop.aspectj.AspectJExpressionPointcut]: No default constructor found; nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:479)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
	at com.myspring.test.Test.main(Test.java:11)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0': Cannot resolve reference to bean 'pointcut' while setting bean property 'pointcut'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pointcut': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.aop.aspectj.AspectJExpressionPointcut]: No default constructor found; nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1531)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1276)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans(BeanFactoryAdvisorRetrievalHelper.java:92)
	at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findCandidateAdvisors(AbstractAdvisorAutoProxyCreator.java:102)
	at org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator.shouldSkip(AspectJAwareAdvisorAutoProxyCreator.java:103)
	at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(AbstractAutoProxyCreator.java:248)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:1037)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:1011)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:473)
	... 10 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pointcut': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.aop.aspectj.AspectJExpressionPointcut]: No default constructor found; nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1155)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1099)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:325)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
	... 26 more
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.aop.aspectj.AspectJExpressionPointcut]: No default constructor found; nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:85)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1147)
	... 32 more
Caused by: java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException
	at java.lang.Class.getDeclaredConstructors0(Native Method)
	at java.lang.Class.privateGetDeclaredConstructors(Class.java:2389)
	at java.lang.Class.getConstructor0(Class.java:2699)
	at java.lang.Class.getDeclaredConstructor(Class.java:1985)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:80)
	... 33 more
Caused by: java.lang.ClassNotFoundException: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException
	at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
	at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
	... 38 more


造成报错的原因是因为缺少两个jar包:aopalliance-1.0.jar和aspectjweaver-1.8.8.jar,

这两个jar包的下载地址:《aop面向切面需要的jar包


将这两个jar包放到项目中,如图:




然后再次运行Test,控制台打印信息如下:




说明spring的aop产生作用了。


接下里我们在Test代码中增加一行调用delete方法的代码,如下:


package com.myspring.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.myspring.service.UserService;

public class Test {

	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml") ;
		UserService userService = (UserService) ac.getBean("userService") ;
		userService.add() ;
		System.out.println("----------------------------");
		userService.delete() ;
	}
	
}


运行Test控制台打印信息如下:




我们发现调用的delete方法,并没有加上日志信息。


这是因为我们在beans.xml配置文件中,aop的日志配置,只配置了add方法,


如图:






如果想要UserServiceImpl类中的所有方法都起作用,那么配置应该改成*号,如下面的代码:


<?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.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
   
	<bean id="userService" class="cn.myspring.service.UserServiceImpl"></bean>
	<bean id="log" class="cn.myspring.log.Log"></bean>
	<aop:config>
		<!-- aop:pointcut切入点配置:
			execution() : 是表达式; 
			*  : 表示所有返回值 ;
			位置 : cn.myspring.service.UserServiceImpl ;
			方法 : * 表示UserServiceImpl类中的所有方法都起作用 ;
		-->
		<aop:pointcut expression="execution(* cn.myspring.service.UserServiceImpl.*())" id="pointcut"/>
		<!-- aop:advisor : 告诉程序,切入点如嵌入的业务有哪些;
			 advice-ref  : 对应的公共业务 ;
			 pointcut-ref: 切入点。
		 -->
		<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
	</aop:config>
</beans>


再次运行Test代码,控制台打印信息如下:




可以看到在add方法和delete方法的前面都打印了日志信息。


如果我们的方法有参数,那么就可以在beans.xml配置aop时,写上两个点,如下:




如果是某一个包下面的所有的类的所有方法都要使用aop嵌入日志信息,那么就可以写成如下:





后置通知


从spring中文帮助文档.chm中可以看到后置通知的实现类如下图:





在cn.myspring.log包下增加AfterLog类,代码如下:


package cn.myspring.log;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

public class AfterLog implements AfterReturningAdvice {

	/**
	 * 目标方法执行后,执行的通知
	 * 
	 * @param returnValue
	 *            : 返回值 ;
	 * @param method
	 *            : 被调用的方法对象 ;
	 * @param args
	 *            : 被调用方法的参数 ;
	 * @param target
	 *            : 被调用的方法对象的目标对象 。
	 */
	@Override
	public void afterReturning(Object returnValue, Method method,
			Object[] args, Object target) throws Throwable {
		System.out.println(target.getClass().getName() + "的" + method.getName()
				+ "被成功执行 , 返回值是 :" + returnValue);
	}

}


在beans.xml中配置文件增加afterLog类的配置和aop配置,代码如下:


<?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.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
   
	<bean id="userService" class="cn.myspring.service.UserServiceImpl"></bean>
	<bean id="log" class="cn.myspring.log.Log"></bean>
	<bean id="afterlog" class="cn.myspring.log.AfterLog"></bean>
	<aop:config>
		<!-- aop:pointcut切入点配置:
			execution() : 是表达式; 
			*  : 表示所有返回值 ;
			位置 : cn.myspring.service.UserServiceImpl ;
			方法 : * 表示UserServiceImpl类中的所有方法都起作用 ;
		-->
		<aop:pointcut expression="execution(* cn.myspring.service.*.*(..))" id="pointcut"/>
		<!-- aop:advisor : 告诉程序,切入点如嵌入的业务有哪些;
			 advice-ref  : 对应的公共业务 ;
			 pointcut-ref: 切入点。
		 -->
		<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
		<aop:advisor advice-ref="afterlog" pointcut-ref="pointcut"/>
	</aop:config>
</beans>


测试类Test代码如下:


package com.myspring.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.myspring.service.UserService;

public class Test {

	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml") ;
		UserService userService = (UserService) ac.getBean("userService") ;
		userService.add() ;

	}
	
}


运行Test代码,控制台打印信息如下:




AOP的重要性:


spring的aop就是将公共的业务(如:日志、安全等)和领域业务结合。当执行领域业务时,将会把公共业务加进、

来。实现公共业务的重复利用。领域业务更纯粹,程序员专注于领域业务。其本质还是动态代理。



第二种方式实现aop:自定义类来实现


项目结构如图:




Log日志类:


package cn.myspring.log;


/**
 * 日志切面
 */
public class Log {
	
	public void before() {
		System.out.println("---方法执行前---");
	}
	
	public void after() {
		System.out.println("---方法执行后---");
	}
	
}


UserService类:


package cn.myspring.service;

/**
 * 抽象角色
 */
public interface UserService {

	public void add() ;
	public void update() ;
	public void delete() ;
	public void search(int a) ;
}


UserServiceImpl类代码:


package cn.myspring.service;

/**
 * 真实角色
 */
public class UserServiceImpl implements UserService {

	@Override
	public void add() {
		System.out.println("增加用户");
	}

	@Override
	public void update() {
		System.out.println("修改用户");
	}

	@Override
	public void delete() {
		System.out.println("删除用户");
	}

	@Override
	public void search(int a) {
		System.out.println("查询用户"+a);
	}
	
}

beans.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.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
   
	<bean id="userService" class="cn.myspring.service.UserServiceImpl"></bean>
	<bean id="log" class="cn.myspring.log.Log"></bean>
	<aop:config>
		<!-- 自定义aop配置
			ref : 关联Log日志类;
		 -->
		<aop:aspect ref="log">
			<aop:pointcut expression="execution(* cn.myspring.service.*.*(..))" id="pointcut"/>
			<aop:before method="before" pointcut-ref="pointcut"/>
			<aop:after method="after" pointcut-ref="pointcut"/>
		</aop:aspect>
	</aop:config>
</beans>

Test类代码:

package com.myspring.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.myspring.service.UserService;

public class Test {

	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml") ;
		UserService userService = (UserService) ac.getBean("userService") ;
		userService.add() ;

	}
	
}


运行Test类,控制台打印信息:





第三种实现方式:通过注解来实现


项目结构如下:




Log类代码如下:


package cn.myspring.log;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;


/**
 * 日志切面
 */
@Aspect
public class Log {
	
	@Before("execution(* cn.myspring.service.*.*(..))")
	public void before() {
		System.out.println("---方法执行前---");
	}
	
	@After("execution(* cn.myspring.service.*.*(..))")
	public void after() {
		System.out.println("---方法执行后---");
	}
	
}


UserServiceImpl代码:


package cn.myspring.service;

/**
 * 抽象角色
 */
public interface UserService {

	public void add() ;
	public void update() ;
	public void delete() ;
	public void search(int a) ;
}


UserServiceImpl代码:


package cn.myspring.service;

/**
 * 真实角色
 */
public class UserServiceImpl implements UserService {

	@Override
	public void add() {
		System.out.println("增加用户");
	}

	@Override
	public void update() {
		System.out.println("修改用户");
	}

	@Override
	public void delete() {
		System.out.println("删除用户");
	}

	@Override
	public void search(int a) {
		System.out.println("查询用户"+a);
	}
	
}


beans.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.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
   
	<bean id="userService" class="cn.myspring.service.UserServiceImpl"></bean>
	<bean id="log" class="cn.myspring.log.Log"></bean>
	<!-- 自动配置aop -->
	<aop:aspectj-autoproxy />
</beans>

Test类同上,运行后控制台打印信息:




当实现环绕通知时,我们在Log类中增加如下代码:


	@Around("execution(* cn.myspring.service.*.*(..))")
	public void around(ProceedingJoinPoint jp) throws Throwable {
		System.out.println("环绕前");
		System.out.println("签名:"+jp.getSignature());
		//执行目标方法
		jp.proceed() ;
		System.out.println("环绕后");
	}
	


增加后Log类代码如图:




执行Test类代码,控制台打印信息如下:





























评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值