Spring AOP学习笔记
AOP是Aspect Oriented Programming的缩写,意思是面向方面编程,一种新兴的编程技术。
AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,
AOP可以说也是这种目标的一种实现。它可以解决OOP和过程化方法不能够很好解决的横切
(crosscut)问题,
如:事务、安全、日志等横切关注。当未来系统变得越来越复杂,
横切关注点就成为一个大问题的时候,AOP就可以很轻松的解决横切关注点这个问题。
比如有这样一个情景:
public class AccountManager { private static final sysLogger = SystemLogger.getInstance(); private AuthorizationManager authMgr = new AuthorizationManager(); public void transferFunds(String from, String to, int amount) { sysLogger.log("transfer funds from " + from + " to " + to); if(authMgr.accessAble(from) && authMgr.accessAble(to)) { sysLogger.log("access successfully"); CustomerAccount from = findAccount(from); CustomerAccount to = findAccount(to); from.debit(amount); to.credit(amount); } else { sysLogger.log("access deny"); } sysLogger.log("transfer funds from " + from + " to " + to + " $" + amount + " successfully!"); } }
package com.royzhou.aop; public interface IUserBean { public void getUser(); public void addUser(); public void updateUser(); public void deleteUser(); }
package com.royzhou.aop; public class UserBean implements IUserBean { private String user = null; public UserBean() { } public UserBean(String user) { this.user = user; } public void setUser(String user) { this.user = user; } public void addUser() { System.out.println("this is addUser() method!"); } public void deleteUser() { System.out.println("this is deleteUser() method!"); } public void getUser() { System.out.println("this is getUser() method!"); } public void updateUser() { System.out.println("this is updateUser() method!"); } }
package com.royzhou.aop; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class JDKProxy implements InvocationHandler { private Object targetObject; public Object createProxyObject(Object targetObject) { this.targetObject = targetObject; //生成代理对象 return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),this.targetObject.getClass().getInterfaces(),this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { UserBean userBean = (UserBean) targetObject; String userName = userBean.getUserName(); Object result = null; //权限判断 if(userName!=null && !"".equals(userName)) { //调用目标对象的方法 result = method.invoke(targetObject, args); } return result; } }
package com.royzhou.aop; public class TestProxy { public static void main(String[] args) { JDKProxy jProxy = new JDKProxy(); IUserBean userBean = (IUserBean) jProxy.createProxyObject(new UserBean("royzhou")); userBean.addUser(); } }
package com.royzhou.aop; public class TestProxy { public static void main(String[] args) { JDKProxy jProxy = new JDKProxy(); IUserBean userBean = (IUserBean) jProxy.createProxyObject(new UserBean()); userBean.addUser(); } }
package com.royzhou.aop; public class UserBean { private String userName = null; public UserBean() { } public UserBean(String userName) { this.userName = userName; } public void addUser() { System.out.println("this is addUser() method!"); } public void deleteUser() { System.out.println("this is deleteUser() method!"); } public void getUser() { System.out.println("this is getUser() method!"); } public void updateUser() { System.out.println("this is updateUser() method!"); } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
package com.royzhou.aop; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CGLibProxy implements MethodInterceptor { private Object targetObject; public Object createProxyObject(Object targetObject) { this.targetObject = targetObject; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.targetObject.getClass()); //非final 进行覆盖 enhancer.setCallback(this); //回调,通过 return enhancer.create(); //创建代理对象 } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { UserBean userBean = (UserBean) targetObject; String userName = userBean.getUserName(); Object result = null; if(userName!=null && !"".equals(userName)) { //调用目标对象的方法 result = methodProxy.invoke(targetObject, args); } return result; } . }
package com.royzhou.aop; public class TestProxy { public static void main(String[] args) { CGLibProxy cProxy = new CGLibProxy(); UserBean userBean = (UserBean) cProxy.createProxyObject(new UserBean("royzhou")); userBean.addUser(); } }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { UserBean userBean = (UserBean) targetObject; String userName = userBean.getUserName(); Object result = null; if(userName!=null && !"".equals(userName)) { //调用目标对象的方法 try { //前置通知 result = method.invoke(targetObject, args); //后置通知 } catch(Exception e) { //例外通知 } finally { //最终通知 } } //环绕通知(前置通知之后,目标对象方法调用之前执行,全部执行完毕(最终通知)之后) return result; }
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <aop:aspectj-autoproxy/> </beans>
package com.royzhou.aop; public interface IUserBean { public void getUser(); public void addUser(); public void updateUser(); public void deleteUser(); }
package com.royzhou.aop; public class UserBean { public void addUser(String userName) { System.out.println("this is addUser() method!"); } public void deleteUser(int userId) { System.out.println("this is deleteUser() method!"); } public String getUser(String userId) { System.out.println("this is getUser() method!"); return "haha"; } public void updateUser(int userId, String userName) { System.out.println("this is updateUser() method!"); } }
package com.royzhou.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; 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; @Aspect public class MyInterceptor { /** * 定义切入点 * 第一个*表示方法的返回值,这里使用通配符,只有返回值符合条件的才拦截,(!void表示有返回值) * 第一个..表示com.royzhou.aop包及其子包 * 倒数第二个*表示包下的所有Java类都被拦截 * 最后一个*表示类的所有方法都被拦截 * (..)表示方法的参数可以任意多个如[(java.lang.String,java.lang.Integer)表示第一个参数是String,第二个参数是int的方法才会被拦截] */ @Pointcut("execution(* com.royzhou.aop..*.*(..))") //定义一个切入点,名称为pointCutMethod(),拦截类的所有方法 private void pointCutMethod() { } @Before("pointCutMethod()") //定义前置通知 public void doBefore() { System.out.println("前置通知"); } @AfterReturning("pointCutMethod()") //定义后置通知 public void doAfterReturning() { System.out.println("后置通知"); } @AfterThrowing("pointCutMethod()") //定义例外通知 public void doAfterException() { System.out.println("异常通知"); } @After("pointCutMethod()") //定义最终通知 public void doAfter() { System.out.println("最终通知"); } @Around("pointCutMethod()") //定义环绕通知 public Object doAround(ProceedingJoinPoint pjp) throws Throwable { System.out.println("进入方法"); Object object = pjp.proceed(); //必须执行pjp.proceed()方法,如果不执行此方法,业务bean的方法以及后续通知都不执行 System.out.println("退出方法"); return object; } }
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <aop:aspectj-autoproxy/> <bean id="MyInterceptor" /> <bean id="UserBean" name="code"> package com.royzhou.aop; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestAOP { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml"); UserBean ub = (UserBean)ctx.getBean("UserBean"); ub.addUser("royzhou"); } }
package com.royzhou.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; 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; @Aspect public class MyInterceptor { /** * 定义切入点 * 第一个*表示方法的返回值,这里使用通配符,只有返回值符合条件的才拦截 * 第一个..表示com.royzhou.aop包及其子包 * 倒数第二个*表示包下的所有Java类 * 最后一个*表示类的所有方法 * (..)表示方法的参数可以任意多个 */ @Pointcut("execution(* com.royzhou.aop..*.*(..))") //定义一个切入点,名称为pointCutMethod(),拦截类的所有方法 private void pointCutMethod() { } //需要两个条件同时成立. args(userName)代表只有一个参数且为String类型 名称必须与doBefore方法的参数名称一样 @Before("pointCutMethod() && args(userName)") //定义前置通知 public void doBefore(String userName) { System.out.println("前置通知" + userName); } @AfterReturning("pointCutMethod()") //定义后置通知 public void doAfterReturning() { System.out.println("后置通知"); } @AfterThrowing("pointCutMethod()") //定义例外通知 public void doAfterException() { System.out.println("异常通知"); } @After("pointCutMethod()") //定义最终通知 public void doAfter() { System.out.println("最终通知"); } @Around("pointCutMethod()") //定义环绕通知 public Object doAround(ProceedingJoinPoint pjp) throws Throwable { System.out.println("进入方法"); Object object = pjp.proceed(); //必须执行pjp.proceed()方法,如果不执行此方法,业务bean的方法以及后续通知都不执行 System.out.println("退出方法"); return object; } }
package com.royzhou.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; 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; @Aspect public class MyInterceptor { /** * 定义切入点 * 第一个*表示方法的返回值,这里使用通配符,只有返回值符合条件的才拦截 * 第一个..表示com.royzhou.aop包及其子包 * 倒数第二个*表示包下的所有Java类 * 最后一个*表示类的所有方法 * (..)表示方法的参数可以任意多个 */ @Pointcut("execution(* com.royzhou.aop..*.*(..))") //定义一个切入点,名称为pointCutMethod(),拦截类的所有方法 private void pointCutMethod() { } //需要两个条件同时成立. args(userName)代表只有一个参数且为String类型 名称必须与doBefore方法的参数名称一样 @Before("pointCutMethod() && args(userName)") //定义前置通知 public void doBefore(String userName) { System.out.println("前置通知" + userName); } //配置returning="result", result必须和doAfterReturning的参数一致 @AfterReturning(pointcut="pointCutMethod()", returning="result") //定义后置通知 public void doAfterReturning(String result) { System.out.println("后置通知" + result); } @AfterThrowing("pointCutMethod()") //定义例外通知 public void doAfterReturning() { System.out.println("异常通知"); } @After("pointCutMethod()") //定义最终通知 public void doAfter() { System.out.println("最终通知"); } @Around("pointCutMethod()") //定义环绕通知 public Object doAround(ProceedingJoinPoint pjp) throws Throwable { System.out.println("进入方法"); Object object = pjp.proceed(); //必须执行pjp.proceed()方法,如果不执行此方法,业务bean的方法以及后续通知都不执行 System.out.println("退出方法"); return object; } }
package com.royzhou.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; 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; @Aspect public class MyInterceptor { /** * 定义切入点 * 第一个*表示方法的返回值,这里使用通配符,只有返回值符合条件的才拦截 * 第一个..表示com.royzhou.aop包及其子包 * 倒数第二个*表示包下的所有Java类 * 最后一个*表示类的所有方法 * (..)表示方法的参数可以任意多个 */ @Pointcut("execution(* com.royzhou.aop..*.*(..))") //定义一个切入点,名称为pointCutMethod(),拦截类的所有方法 private void pointCutMethod() { } //需要两个条件同时成立. args(userName)代表只有一个参数且为String类型 名称必须与doBefore方法的参数名称一样 @Before("pointCutMethod() && args(userName)") //定义前置通知 public void doBefore(String userName) { System.out.println("前置通知" + userName); } //配置returning="result", result必须和doAfterReturning的参数一致 @AfterReturning(pointcut="pointCutMethod()", returning="result") //定义后置通知 public void doAfterReturning(String result) { System.out.println("后置通知" + result); } //类似returning的配置 @AfterThrowing(pointcut="pointCutMethod()", throwing="e") //定义例外通知 public void doAfterException(Exception e) { System.out.println("异常通知"); } @After("pointCutMethod()") //定义最终通知 public void doAfter() { System.out.println("最终通知"); } @Around("pointCutMethod()") //定义环绕通知 public Object doAround(ProceedingJoinPoint pjp) throws Throwable { System.out.println("进入方法"); Object object = pjp.proceed(); //必须执行pjp.proceed()方法,如果不执行此方法,业务bean的方法以及后续通知都不执行 System.out.println("退出方法"); return object; } }
package com.royzhou.aop; import org.aspectj.lang.ProceedingJoinPoint; public class MyInterceptor { public void doBefore(String userName) { System.out.println("前置通知" + userName); } public void doAfterReturning(String result) { System.out.println("后置通知" + result); } public void doAfterException(Exception e) { System.out.println("异常通知"); } public void doAfter() { System.out.println("最终通知"); } public Object doAround(ProceedingJoinPoint pjp) throws Throwable { System.out.println("进入方法"); Object object = pjp.proceed(); //必须执行pjp.proceed()方法,如果不执行此方法,业务bean的方法以及后续通知都不执行 System.out.println("退出方法"); return object; } }
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <aop:aspectj-autoproxy/> <bean id="aspjectbean" /> <bean id="UserBean" ref="aspjectbean"> <aop:pointcut id="mycut" expression="execution(* com.royzhou.aop..*.*(..))"/> <aop:before pointcut="execution(* com.royzhou.aop..*.*(..)) and args(userName)" method="doBefore" /> <aop:after-returning pointcut-ref="mycut" method="doAfterReturning" returning="result" /> <aop:after-throwing pointcut-ref="mycut" method="doAfterReturning" throwing="e" /> <aop:after pointcut-ref="mycut" method="doAfter"/> <aop:around pointcut-ref="mycut" method="doArround"/> </aop:aspect> </aop:config> </beans>