AOP在事务处理、日志、安全等方面用的很多,在日常软件定制开发中,用好AOP可以进一步解耦,增强代码的可复用性。平时用的最多的还是Spring AOP动态代理,其用法如下:
第一种实现的方式:通过Spring的API实现AOP。
第一步:
public interface UserService {public void add();public void update(int a);public void delete();public void search();}第二步:
public class UserServiceImpl implements UserService {@Overridepublic void add() {System.out.println("增加用户");}@Overridepublic void update(int a) {System.out.println("修改用户");}@Overridepublic void delete() {System.out.println("删除用户");}@Overridepublic void search() {System.out.println("查询用户");}第三步:实现MethodBeforeAdvice的接口,Spring框架当中为我们提供了很多中通知。
public class Log implements MethodBeforeAdvice{/*** @param method 被调用方法对象* @param args 被调用的方法的参数* @param target 被调用的方法的目标对象* */@Overridepublic void before(Method method, Object[] args, Object target)throws Throwable {System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行");}}第四步:配置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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://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>第五步:测试:
package com.spring.test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.spring.service.UserService;public class Test {public static void main(String[] args) {ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");UserService userService = (UserService)ac.getBean("userService");userService.update(2);userService.add();}}运行结果:
三月 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 被调用的方法对象的目标对象* */@Overridepublic 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被成功执行,返回值是:nullcom.spring.service.impl.UserServiceImpl的add方法被执行增加用户com.spring.service.impl.UserServiceImpl的add被成功执行,返回值是:null总结:AOP的重要性,非常重要Spring的AOP就是将公共的业务(如日志,安全等)和业务类结合。当执行业务的时候将会把公共业务加进来。实现公共业务的重复利用。我们自己的业务就会变得更加的纯粹,我们就可以关注我们的自己的业务,本质就是动态代理。第二种方式:自定义类来实现AOP,不实现spring的自带的通知第一步:重新通知:
public class Log {public void before(){System.out.println("方法执行前");}public void after(){System.out.println("方法执行后");}}第二步:重新写配置文件
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://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;@Aspectpublic 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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://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)方法执行前修改用户环绕后方法执行后里面最关键的切面配置如下:
原文:http://www.cnblogs.com/doit8791/p/7697689.html