为什么会有面向切面编程(AOP)?我们知道Java是一个面向工具(OOP)的语言,但它有一些漏洞,好比当我们需要为多个不具有担任干系的工具引入一个民众行为,譬喻日志、权限验证、事务等成果时,只能在在每个工具里引用民众行为。这样做未便于维护,并且有大量反复代码。AOP的呈现补充了OOP的这点不敷。
为了叙述清楚Spring AOP,我们从将以下方面举办接头:
1. 署理模式
署理模式:为其他工具提供一种署理以节制对这个工具的会见。这段话较量官方,但我更倾向于用本身的语言领略:好比A工具要做一件工作,在没有署理前,本身来做;在对 A 署理后,由 A 的署理类 B 来做。署理其实是在原实例前后加了一层处理惩罚,这也是 AOP 的低级表面。
2. 静态署理道理及实践
静态署理模式:静态署理说白了,劳务派遣管理系统,昆山软件开发,就是在措施运行前就已经存在署理类的字节码文件、署理类和原始类的干系在运行前就已经确定。空话不多说,我们看一下代码。为了利便阅读,博主把单独的 class 文件归并到接口中,读者可以直接复制代码运行:
package test.staticProxy; // 接口 public interface IUserDao { void save(); void find(); } //方针工具 class UserDao implements IUserDao{ @Override public void save() { System.out.println("模仿:生存用户!"); } @Override public void find() { System.out.println("模仿:查询用户"); } } /** * 静态署理 * 特点: * 2. 方针工具必需要实现接口 * 2. 署理工具,要实现与方针工具一样的接口 */ class UserDaoProxy implements IUserDao{ // 署理工具,需要维护一个方针工具 private IUserDao target = new UserDao(); @Override public void save() { System.out.println("署理操纵: 开启事务..."); target.save(); // 执行方针工具的要领 System.out.println("署理操纵:提交事务..."); } @Override public void find() { target.find(); } }
测试功效:
苏州软件定制开拓 博主一小我私家的气力有限" class="aligncenter size-full wp-image-31321" title="aop-1" src="/uploads/allimg/c190113/154I2350ZKF-14058.png" />
静态署理固然担保了业务类只需存眷逻辑自己,署理工具的一个接口只处事于一种范例的工具。假如要署理的要领许多,势须要为每一种要领都举办署理。再者,假如增加一个要领,除了实现类需要实现这个要领外,所有的署理类也要实现此要领。增加了代码的维护本钱。那么要如何办理呢?谜底是利用动态署理。
3. 动态署理道理及实践
动态署理模式:动态署理类的源码是在措施运行期间,通过 JVM 反射等机制动态生成。署理类和委托类的干系是运行时才确定的。实譬喻下:
package test.dynamicProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; // 接口 public interface IUserDao { void save(); void find(); } //方针工具 class UserDao implements IUserDao{ @Override public void save() { System.out.println("模仿: 生存用户!"); } @Override public void find() { System.out.println("查询"); } } /** * 动态署理: * 署理工场,给多个方针工具生成署理工具! * */ class ProxyFactory { // 吸收一个方针工具 private Object target; public ProxyFactory(Object target) { this.target = target; } // 返回对方针工具(target)署理后的工具(proxy) public Object getProxyInstance() { Object proxy = Proxy.newProxyInstance( target.getClass().getClassLoader(), // 方针工具利用的类加载器 target.getClass().getInterfaces(), // 方针工具实现的所有接口 new InvocationHandler() { // 执行署理工具要领时候触发 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 获取当前执行的要领的要领名 String methodName = method.getName(); // 要领返回值 Object result = null; if ("find".equals(methodName)) { // 直接挪用方针工具要领 result = method.invoke(target, args); } else { System.out.println("开启事务..."); // 执行方针工具要领 result = method.invoke(target, args); System.out.println("提交事务..."); } return result; } } ); return proxy; } }
测试功效如下: