spring(二):简单阐述springAOP的实现原理

前言:

  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

 

 

猜你喜欢

转载自www.cnblogs.com/yangji0202/p/10932403.html