SPRING系列五之 AOP

AOP概念

AOP说简单点就是将与业务不相关的代码进行分离,例如日志,权限,事务处理等。降低业务实现与不相关功能的耦合性,提高代码的重用性和易于维护,便是AOP所要做的事情。

Java代理机制

先不使用AOP,看看传统的Java代理机制,代码如下。

(1)编写一个日志信息的代理类,实现InvocationHandler接口
编写一个业务接口,并实现这个接口。

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.logging.Level;
    import java.util.logging.Logger;

    /**
     * Created by jeysine on 2017/3/30.
     */
    public class LogProxy implements InvocationHandler {
        private Logger logger = Logger.getLogger(this.getClass().getName());
        private Object delegate;
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object result = null;
            try {
                Long time = System.currentTimeMillis();
                logger.log(Level.INFO, "开始执行方法");
                result = method.invoke(delegate,args);
                logger.log(Level.INFO, "执行方法结束");
                time = System.currentTimeMillis() - time;
                logger.log(Level.INFO, "耗时" + time + "毫秒");
            }catch (Exception e){
                logger.log(Level.INFO,e.toString());
            }
            return result;
        }

        public Object bind(Object delegate) {
            this.delegate = delegate;
            return Proxy.newProxyInstance(delegate.getClass().getClassLoader(),delegate.getClass().getInterfaces(),this);
        }
    }

(2)编写业务接口并实现该接口。

    /**
     * Created by jeysine on 2017/3/30.
     */
    public interface BussinessInterface {
        public void insert();
    }
    public class BussinessImpl implements BussinessInterface {
        @Override
    public void insert() {
        for(int i = 0; i < 100000 ; i++){
            //做一个耗时操作
        }
        System.out.println("执行insert方法");
    }
    }

(3)编写测试类。

    /**
     * Created by jeysine on 2017/3/30.
     */
    public class TestMain {
        public static void  main(String[] args){
            LogProxy logProxy = new LogProxy();
            BussinessInterface bussinessInterface = (BussinessInterface) logProxy.bind(new BussinessImpl());
            bussinessInterface.insert();
        }
    }

(4)测试结果。

执行insert方法
三月 30, 2017 2:07:13 下午 com.jeysine.weishop.test.LogProxy invoke
信息: 开始执行方法
三月 30, 2017 2:07:13 下午 com.jeysine.weishop.test.LogProxy invoke
信息: 执行方法结束
三月 30, 2017 2:07:13 下午 com.jeysine.weishop.test.LogProxy invoke
信息: 耗时117毫秒
AOP的自动代理

接下来使用AOP来实现该功能。
(1)先写个Before通知,也就是在切点之前执行的类,实现MethodBeforeAdvice接口代码如下:

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Created by jeysine on 2017/3/30.
 */
public class LogBefore implements MethodBeforeAdvice {
    private Logger logger = Logger.getLogger(this.getClass().getName());
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        logger.log(Level.INFO, "开始执行方法");
    }
}

(2)再写个After通知,在切点运行之后执行,实现AfterReturningAdvice接口,代码如下:

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Created by jeysine on 2017/3/30.
 */
public class LogAfter implements AfterReturningAdvice {
    private Logger logger = Logger.getLogger(this.getClass().getName());
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        logger.log(Level.INFO,"执行方法结束");
    }
}

(3)业务接口和实现类与前面的例子相同,就是BussinessInterface和BussinessImpl。

(4)配置Spring的AOP

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--配置业务类-->
    <bean id="bussiness" class="com.jeysine.weishop.test.BussinessImpl" />

    <!--配置before通知-->
    <bean id="logBefore" class="com.jeysine.weishop.test.LogBefore" />
    <bean id="logBeforeAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="advice" ref="logBefore"/>
        <property name="patterns">
            <!--采用正则表达式,如下是对所有方法进行-->
            <value>.*.*</value>
        </property>
    </bean>

    <!--配置after通知-->
    <bean id="logAfter" class="com.jeysine.weishop.test.LogAfter" />
    <bean id="logAfterAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="advice" ref="logAfter"/>
        <property name="patterns">
            <!--采用正则表达式,如下是对所有方法进行-->
            <value>.*.*</value>
        </property>
    </bean>
</beans>

(5)编写测试类

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

/**
 * Created by jeysine on 2017/3/30.
 */
public class TestMain {
    public static void  main(String[] args){
        ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:config.xml");
        BussinessInterface bussinessInterface = (BussinessInterface)applicationContext.getBean("bussiness");
        bussinessInterface.insert();

    }
}

(6)运行结果如下:

15:12:28.562 [main] INFO  o.s.b.f.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [config.xml]
执行insert方法
三月 30, 2017 3:12:28 下午 com.jeysine.weishop.test.LogBefore before
信息: 开始执行方法
三月 30, 2017 3:12:28 下午 com.jeysine.weishop.test.LogAfter afterReturning
信息: 执行方法结束
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值