Spring AOP前置通知实例讲解与AOP详细解析

 

1、引出问题

  有个接口TestServiceInter,有两个实现方法TestService和Test2Service。他们都有sayHello();咱们的需求是在调用这两个方法以前,要先完成写日志的功能;html

2、菜鸟的想法

  我在各个实现类的sayHello()方法里面写上写日志的功能就是了。spring

  这样实现存在的问题:代码冗余。当全部实现类都要加上日志功能的时候,须要写不少重复代码

3、利用AOP前置通知实现此功能

3.1 第一步:咱们须要定义一个接口  

 
package com.jdc.aop;/**
 * @author DEllComputer
 * @Title: TestService
 * @ProjectName SpringAop
 * @Description:
 * @date 2018/12/251:38 PM */public interface TestService {    /**
      * @Description:
      * @param ${tags}
      * @return ${return_type}
      * @throws
      * @author jdc
      * @date 2018/12/25 1:39 PM
      */
    void sayHi(String name);

}
 

3.2 第二步:实现接口

 
public class TestServiceImpl implements TestService {    private String name;    /**
      * @Description: say hi
      * @param ${tags}
      * @return ${return_type}
      * @throws
      * @author jdc
      * @date 2018/12/25 1:40 PM
      */
    @Override    public void sayHi(String name ) {
        System.out.println("hi:" + name);
    }    public String getName() {        return name;
    }    public void setName(String name) {        this.name = name;
    }
}
 

3.3 第三步:实现前置通知(AOP中通知的概念就是实现加强代码逻辑的,好比这里的记录日志)

 
/**
 * @author DEllComputer
 * @Title: MyBeforeAdvice
 * @ProjectName SpringAop
 * @Description: 写日志前置通知
 * @date 2018/12/251:42 PM */public class MyBeforeAdvice implements MethodBeforeAdvice {   
    /**
      * @Description: 写日志的功能
      * @param ${tags} 
      * @return ${return_type} 
      * @throws
      * @author jdc
      * @date 2018/12/25 1:44 PM 
      */
    @Override    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("我是写日志的功能。");
    }
}
 

前置通知须要实现MethodBeforeAdvice接口,前置通知是在目标方法调用以前调用;ide

3.4 第四步:在Spring的配置文件中配置代理对象,通知,目标对象

<?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="myBeforeAdvice" class="com.jdc.aop.advice.MyBeforeAdvice"/>

    <!-- 配置被代理对象 -->
    <bean id="logTestServiceImpl" class="com.jdc.aop.TestServiceImpl">
        <property name="name" value="Test"></property>
    </bean>

    <!-- 配置代理对象 -->
    <bean id="proxyFactoryBean"   class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 代理接口集 配置哪些接口要被代理 -->
        <property name="proxyInterfaces">
            <list>
                <value>com.jdc.aop.TestService</value>
            </list>
        </property>

        <!-- 把通知织入代理对象 -->
        <property name="interceptorNames">
            <value>myBeforeAdvice</value>
        </property>

        <!-- 配置被代理的对象 -->
        <property name="target" ref="logTestServiceImpl"/>


    </bean>
    
</beans>
 
    ProxyFactoryBean是一个代理对象,若是咱们被代理的对象实现了接口,Spring使用的是jdk动态代理技术实现的动态代理;因此咱们要告诉代理对象,咱们的哪
些接口须要被代理,而后哪一个对象须要被代理,个人加强实现应该怎么被织入到代理对象(前置,后置,环绕....)

3.5 第五步:写测试代码测试

 
public class TestMain {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
                //获取代理对象
        TestService log = (TestService) ac.getBean("proxyFactoryBean");
        log.sayHi("哈哈");

    }
}
 

注意这里,咱们须要获取代理对象,而不是目标对象,否则不能调用前置通知的代码。测试