前言:
AOP技术利用一种称为“横切”的技术,解剖封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,
这样就能减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
实现原理:
AOP通俗的来说就是在某个方法执行前后插入一些代码,非常有名的就是日志功能了。但是为了代码的耦合性又不能把这些代码写死到
某个方法中,把这些代码提取出来封装到一个模块中,由AOP指定插入位置。
springAOP实现原理用到了代理模式和反射。虽然我们自己没法造轮子写一个AOP,但是这里举一个代码例子模拟AOP如何工作的,使用的
是JDK的动态代理。
1.准备一个pojo类
Account.java
package com.cnblogs.aop.pojo;
/**
* 简单模拟银行账户
*
*/
public class Account {
// 卡号
private Long id;
// 姓名
private String name;
//余额
private double balance;
public Account() {
super();
// TODO Auto-generated constructor stub
}
public Account(Long id, String name, double balance) {
super();
this.id = id;
this.name = name;
this.balance = balance;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
2.准备一个接口,可以在这个接口中定义许多服务方法。这里仅一个存钱的方法
AccountService.java
package com.cnblogs.aop.theory.service;
public interface AccountService {
/**
* 存钱
* @param money
*/
public abstract void save(double money);
}
它的实现类AccountServiceImpl.java
package com.cnblogs.aop.theory.service.serviceImpl;
import com.cnblogs.aop.pojo.Account;
import com.cnblogs.aop.theory.service.AccountService;
public class AccountServiceImpl implements AccountService{
private Account account;
public AccountServiceImpl(Account account) {
this.account = account;
}
@Override
public void save(double money) {
account.setBalance(account.getBalance() + money);
System.out.println("当前余额为: " + account.getBalance() );
}
}
3.准备切面类,这个就是需要插入方法前后的那些代码。
Log.java
package com.cnblogs.aop.theory.log;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 日志功能
* 记录操作时间
*
*/
public class Log {
public void before(){
System.out.println("操作开始时间: " + new SimpleDateFormat().format(new Date()));
}
public void after(){
System.out.println("操作结束时间: " + new SimpleDateFormat().format(new Date()));
}
}
4.代理类。重点部分
package com.cnblogs.aop.theory.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理
*
*/
public class DynAccountService implements InvocationHandler{
// 目标对象
private Object target;
public DynAccountService(Object target) {
this.target = target;
}
/**
* 给目标对象生成代理对象
*/
public Object bind(){
return Proxy.newProxyInstance(this.target.getClass().getClassLoader(),
this.target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 利用反射获得日志对象
Class<?> log = Class.forName("com.cnblogs.aop.theory.log.Log");
// 获得before()
Method before = log.getMethod("before");
// 获得after()
Method after = log.getMethod("after");
// 添加额外功能
before.invoke(log.newInstance());
// 运行目标对象方法
method.invoke(this.target, args);
// 添加额外功能
after.invoke(log.newInstance());
return null;
}
}
(1):static Object newProxyInstance(ClassLoader<?> loader,Class(?)[] interface, InvocationHandler handler)
1.loader: 目标对象的类加载器
2.interface:目标对象实现的接口
3.handler:事件处理,执行目标对象的方法时,会触发事件处理器的invoke方法,并把执行目标对象方法传入invoke中
(2):在invoke方法中利用反射获得切面类日志对象,为的是代理类和日志类解耦。
5.测试方法和结果
package com.cnblogs.aop.theory.jtest;
import com.cnblogs.aop.pojo.Account;
import com.cnblogs.aop.theory.proxy.DynAccountService;
import com.cnblogs.aop.theory.service.AccountService;
import com.cnblogs.aop.theory.service.serviceImpl.AccountServiceImpl;
public class TheoryTest {
public static void main(String[] args) {
Account account = new Account(6217L, "zs", 5000.0);
// 获得代理对象
AccountService service = (AccountService) new DynAccountService(new AccountServiceImpl(account)).bind();
// 执行目标对象的方法
service.save(1000);
}
}
结果:
操作开始时间: 19-5-27 下午7:05
当前余额为: 6000.0
操作结束时间: 19-5-27 下午7:05
原文:https://www.cnblogs.com/yangji0202/p/10932403.html