spring (2): The simplest explanation of the implementation of the principle of springAOP

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

 

 

Guess you like

Origin www.cnblogs.com/yangji0202/p/10932403.html