java动态代理机制的功能十分强大,使用动态代理技术能够有效的降低应用中各个对象之间的耦合紧密程度,提高开发的效率以及程序的可维护性,事实上Spring AOP就是建立在Java动态代理的基础之上。其实AOP、IOC、动态代理、序列化等技术与设计思想都是结合在一起使用的,要想做好一个功能强大齐全的系统,这些技术搜需要我们取学习整合的。
开始搬砖
1.创建接口去让我们的实体类去实现其中的方法及属性,也就是我们的用户权限
package com.icommon.aoptest; public interface AopInterface { Integer getAopId(); void setAopId(Integer aopid); }
package com.icommon.aoptest; public class UserCommonInfo implements AopInterface {//实现AopInterface接口,后续将权限参数直接注入到接口中,这样实体类获取到也是该权限值 @Override public String toString() { return "User [id=" + id + ", name=" + name + ", age=" + age + ", aopId=" + aopId + "]"; } private Integer id; private String name; private Integer age; private Integer aopId; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Integer getAopId() { return aopId; } public void setAopId(Integer aopid) { this.aopId = aopid; } }
2.实现MethodInterceptor 为Spring AOP完成注入通知
package com.icommon.aoptest; import org.aopalliance.intercept.MethodInvocation; public interface ServiceBeforeAdvice { void handler(MethodInvocation invocation); }
3.AOPAdvice实现ServiceBeforeAdvice作为整个参数调度的类
package com.icommon.aoptest; import org.aopalliance.intercept.MethodInvocation; import com.icommon.exception.OPMException; public abstract class AopAdvice implements ServiceBeforeAdvice { @Override public void handler(MethodInvocation invocation) { String name = "Tom"; if(needIntercept(name,invocation)){ handler(name,invocation); } } public abstract boolean needIntercept(String name, MethodInvocation invocation); public abstract void handler(String name, MethodInvocation invocation); protected static void initVpnId(String name, AopInterface bean){ if(name.equals("Tom")){ bean.setAopId(12); } } protected static void checkVPNAuthority(String name, AopInterface bean){ String text = "not equel!!!"; Integer aopId = bean.getAopId(); if(aopId != 25){ throw new OPMException(text); } } }
4.添加通知ADDAdvice
package com.icommon.aoptest; import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInvocation; public class AddAdvice extends AopAdvice{ public static final AddAdvice INSTANCE = new AddAdvice(); private static Method SEND_ONE_COMMAND_METHOD = null; private AddAdvice(){ } @Override public boolean needIntercept(String name, MethodInvocation invocation) { if (invocation.getMethod() !=SEND_ONE_COMMAND_METHOD && invocation.getArguments()[1] instanceof AopInterface) { OperationEnum ope = (OperationEnum) invocation.getArguments()[0]; if (ope == OperationEnum.ADD) { return true; } } return false; } @Override public void handler(String name, MethodInvocation invocation) { AopInterface bean = (AopInterface) invocation.getArguments()[1]; initVpnId(name, bean); } }
5.注册实例,这里可采用单例,在服务启动时只允许有一个此实例
package com.icommon.aoptest; import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInvocation; public class AddAdvice extends AopAdvice{ public static final AddAdvice INSTANCE = new AddAdvice(); private static Method SEND_ONE_COMMAND_METHOD = null; private AddAdvice(){ } @Override public boolean needIntercept(String name, MethodInvocation invocation) { if (invocation.getMethod() !=SEND_ONE_COMMAND_METHOD && invocation.getArguments()[1] instanceof AopInterface) { OperationEnum ope = (OperationEnum) invocation.getArguments()[0]; if (ope == OperationEnum.ADD) { return true; } } return false; } @Override public void handler(String name, MethodInvocation invocation) { AopInterface bean = (AopInterface) invocation.getArguments()[1]; initVpnId(name, bean); } }
6.封装一些常量
package com.icommon.aoptest; public enum OperationEnum { ADD, DEL }
7.进行通知
package com.icommon.aoptest; import java.util.ArrayList; import java.util.List; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class AopProxyFactoryBean implements MethodInterceptor{ private static List<ServiceBeforeAdvice> advices = new ArrayList<ServiceBeforeAdvice>(); public static void registe(ServiceBeforeAdvice advice) { if (!advices.contains(advice)) { advices.add(advice); } } @Override public Object invoke(MethodInvocation invocation) throws Throwable { Object obj = invocation.proceed(); for(ServiceBeforeAdvice advice:advices){ advice.handler(invocation); } return obj; } }
9.配置信息
<?xml version="1.0"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id ="aopProxyFactoryBean" class="com.icommon.aoptest.AopProxyFactoryBean"/> <bean id ="userService" class="com.icommon.serviceimpl.UserManagerImpl"/> <bean id ="test" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="interceptorNames"> <list> <value>aopProxyFactoryBean</value> </list> </property> <property name="target" ref="userService"></property> <property name="proxyTargetClass" value="true"></property> </bean> </beans>
10.测试(模拟服务启动、实体类参数赋值)
package com.icommon.aoptest; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.icommon.service.UserManager; public class TestAop { @SuppressWarnings("resource") public static void main(String[] args) { Integer id = 2; String name = "Susan"; Integer age = 16; UserCommonInfo user = new UserCommonInfo(); user.setId(id); user.setName(name); user.setAge(age); StartInitDate.registeAdvice(); ApplicationContext cx = new ClassPathXmlApplicationContext("bean.xml"); UserManager useripm = (UserManager) cx.getBean("test"); useripm.addUser(OperationEnum.ADD, user); System.out.println("AOP "+user.toString()); } }
11,运行结果
UserUser [id=2, name=Susan, age=16, aopId=null]
AOP User [id=2, name=Susan, age=16, aopId=12]