第一步:
public interface UserService { public void add(); public void update(int a); public void delete(); public void search(); }
第二步:
第三步:实现MethodBeforeAdvice的接口,Spring框架当中为我们提供了很多中通知。
第四步:配置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="com.spring.service.impl.UserServiceImpl"/> <!-- 这个切面也要配置成bean--> <bean id="log" class="com.spring.advice.Log"/> <aop:config> <!--切入点,需要告诉方法在什么去执行 expression="execution(* com.spring.service.impl.*.*(..))" 第一个* 表示所有的返回值,然后就是包名 第二个*表示所有的类对象 第三个*表示类对象所有的方法 第四个*表示所有方法下面的带参数的方法或者是不带参数的方法 --> <aop:pointcut expression="execution(* com.spring.service.impl.*.*(..))" id="pointcut"/> <!-- 在所有的方法中都切入前置通知--> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> </aop:config> </beans>
第五步:测试:
运行结果:
三月 12, 2017 2:22:44 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@439f5b3d: startup date [Sun Mar 12 14:22:44 GMT+08:00 2017]; root of context hierarchy 三月 12, 2017 2:22:44 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [beans.xml] com.spring.service.impl.UserServiceImpl的update方法被执行 修改用户 com.spring.service.impl.UserServiceImpl的add方法被执行 增加用户 故前置通知可以在spring当中被执行,接下可以完善通知;
方法执行后的----------------------------
public class AfterLog implements AfterReturningAdvice{
/**
* 目标方法执行后执行的通知
* returnValue--返回值
* method 被调用的方法对象
* args 被调用的方法对象的参数
* target 被调用的方法对象的目标对象
* */
@Override
public void afterReturning(Object returnValue, Method method,
Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"被成功执行,返回值是:"+returnValue);
}
}
import java.lang.reflect.Method; import org.springframework.aop.ThrowsAdvice; public class ExceptionLog implements ThrowsAdvice { public void afterThrowing(Method method,Exception ex) throws Throwable { } }
重新配置:
<!-- 这个切面也要配置成bean--> <bean id="log" class="com.spring.advice.Log"/> <bean id="afterLog" class="com.spring.advice.AfterLog"></bean> <aop:config> <!--切入点,需要告诉方法在什么去执行 expression="execution(* com.spring.service.impl.*.*(..))" 第一个* 表示所有的返回值,然后就是包名 第二个*表示所有的类对象 第三个*表示类对象所有的方法 第四个*表示所有方法下面的带参数的方法或者是不带参数的方法 --> <aop:pointcut expression="execution(* com.spring.service.impl.*.*(..))" id="pointcut"/> <!-- 在所有的方法中都切入前置通知--> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config>
测试运行结果:
三月 12, 2017 2:28:19 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@439f5b3d: startup date [Sun Mar 12 14:28:19 GMT+08:00 2017]; root of context hierarchy
三月 12, 2017 2:28:19 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans.xml]
com.spring.service.impl.UserServiceImpl的update方法被执行
修改用户
com.spring.service.impl.UserServiceImpl的update被成功执行,返回值是:null
com.spring.service.impl.UserServiceImpl的add方法被执行
增加用户
com.spring.service.impl.UserServiceImpl的add被成功执行,返回值是:null
总结:AOP的重要性,非常重要
Spring的AOP就是将公共的业务(如日志,安全等)和业务类结合。当执行业务的时候将会把公共业务加进来。实现公共业务的重复利用。我们自己的业务就会变得更加的纯粹,我们就可以关注我们的自己的业务,本质就是动态代理。
第二种方式:自定义类来实现AOP,不实现spring的自带的通知
第一步:重新通知:
第二步:重新写配置文件
<?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="com.spring.service.impl.UserServiceImpl"/> <!-- 这个切面也要配置成bean--> <bean id="log" class="com.spring.advice.Log"/> <aop:config> <!--切入点,需要告诉方法在什么去执行 expression="execution(* com.spring.service.impl.*.*(..))" 第一个* 表示所有的返回值,然后就是包名 第二个*表示所有的类对象 第三个*表示类对象所有的方法 第四个*表示所有方法下面的带参数的方法或者是不带参数的方法 --> <aop:aspect ref="log"> <aop:pointcut expression="execution(* com.spring.service.impl.*.*(..))" id="pointcut"/> <aop:before method="before" pointcut-ref="pointcut"/> <aop:after method="after" pointcut-ref="pointcut"/> </aop:aspect> </aop:config> </beans>
第三种方式:通过注解实现AOP
第一步:修改log
package com.spring.advice; import java.lang.reflect.Method; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.aop.MethodBeforeAdvice; @Aspect public class Log { @Before("execution(* com.spring.service.impl.*.*(..))") public void before(){ System.out.println("方法执行前"); } @After("execution(* com.spring.service.impl.*.*(..))") public void after(){ System.out.println("方法执行后"); } @Around("execution(* com.spring.service.impl.*.*(..))") public Object around(ProceedingJoinPoint jp) throws Throwable{ System.out.println("环绕前"); System.out.println("方法"+jp.getSignature()); Object result=jp.proceed(); System.out.println("环绕后"); return result; } }
第二步:修改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="com.spring.service.impl.UserServiceImpl"/> <!-- 这个切面也要配置成bean--> <bean id="log" class="com.spring.advice.Log"/> <aop:aspectj-autoproxy/> </beans>
第三步:运行:
三月 12, 2017 3:00:02 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@439f5b3d: startup date [Sun Mar 12 15:00:02 GMT+08:00 2017]; root of context hierarchy
三月 12, 2017 3:00:02 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans.xml]
环绕前
方法void com.spring.service.UserService.update(int)
方法执行前
修改用户
环绕后
方法执行后