Preface:
AOP techniques utilize called " cross " technique, anatomical objects inside the package, and those that affect the behavior of the public classes encapsulated into a plurality of reusable modules,
This will reduce duplication of code systems, to reduce the coupling between modules, and facilitates future operability and maintainability.
The principle:
AOP popular it is to insert some code before and after the execution of a method, very famous is the log function. But to the coupling of the code can not write code to death
In one method, the extracted code into a module package, the AOP specified insertion position.
springAOP The principle uses proxy mode and reflection. Although we can not build their own wheels write a AOP, but Here's an example of code that simulate how AOP works, use
It is JDK dynamic proxy.
1. Prepare a class pojo
Account.java
Package Penalty for com.cnblogs.aop.pojo;
/ **
* Simple analog bank account
*
* /
public class the Account {
// card number
Private Long the above mentioned id;
// Name
Private String name;
// balance
Private Double Balance;
public the Account () {
Super ();
// the TODO Auto-Generated Stub constructor
}
public the Account (ID Long, String name, Double Balance) {
Super ();
the 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. Prepare an interface, you can define a number of service method in this interface. Here only one way to save money
AccountService.java
package com.cnblogs.aop.theory.service;
public interface AccountService {
/**
* 存钱
* @param money
*/
public abstract void save(double money);
}
Its implementation class 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