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]
