为什么会有面向切面编程(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;
}
}
测试功效如下: