Spring-Aop

一.AOP(Aspect Oriented Programing)面向切面编程

AOP的终极目标:让我们可以专心做事

下面通过一个例子来介绍AOP的具体使用

案例的要求:使用AOP实现日志记录系统 ,  核心模块  和    增强  单独  开发  ,运行时再组装

首先定义接口和方法

接口和实现类中的代码,我放在一起了,应该比较简单

复制代码
package demo04.dao;

/**
 * Created by mycom on 2018/3/5.
 */
public interface IHelloDao {
    public void doSome();
}


package demo04.dao;

/**
* Created by mycom on 2018/3/5.
*/
public class HelloDaoImpl implements IHelloDao {
public void doSome() {
System.out.println("已经成功加入到DB中了");
}
}


package demo04.service;

/**
* Created by mycom on 2018/3/5.
*/
public interface IHelloService {
public void doSome();
}


package demo04.service;

import demo04.dao.IHelloDao;

/**
* Created by mycom on 2018/3/5.
*/
public class HelloServiceImpl implements IHelloService {
//创建一个Dao的对象
IHelloDao dao;

public IHelloDao getDao() {
return dao;
}

public void setDao(IHelloDao dao) {
this.dao = dao;
}

public void doSome() {
dao.doSome();
}
}


复制代码

同样在resources下面也要有一个xml文件----applicationContext.xml

复制代码
<!--返回的类型只能是实现类-->  这里需要注意一下  class的值只能是实现类的包
    <bean id="dao" class="demo04.dao.HelloDaoImpl">
    </bean>

    <bean id="service" class="demo04.service.HelloServiceImpl">
        <property name="dao" ref="dao"></property>
    </bean>
复制代码

然后编写测试类进行测试

复制代码
@Test
    public void t1(){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContextAop.xml");
        //这里的返回值只能是接口
        IHelloService service =(IHelloService) context.getBean("service");
        service.doSome();
    }
复制代码

运行的结果

现在我们要在这句话出现之前,先记录一下日志,出现之后,再出现一句话

首先要创建一个新的包AOP包,并且在包下面写两个类

LoggerAfter是后置增强

LoggerBefore是前置增强

这两个类中的代码如下

复制代码
package demo04.aop;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

/**
 * Created by mycom on 2018/3/5.
 */
public class LoggerAfter implements AfterReturningAdvice {
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("=======after");
    }
}
复制代码
复制代码
package demo04.aop;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

/**
 * Created by mycom on 2018/3/5.
 */
public class LoggerBefore implements MethodBeforeAdvice {
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("日志记录");
    }
}
复制代码

在xml中配置,在配置xml是要给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" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
复制代码
复制代码
<bean id="service" class="demo04.service.HelloServiceImpl">
        <property name="dao" ref="dao"></property>
    </bean>
    <!--前置-->
    <bean id="beforeAdvice" class="demo04.aop.LoggerBefore">
    </bean>
    <!--后置-->
    <bean id="afterAdvice" class="demo04.aop.LoggerAfter">
    </bean>
    <!--配置aop-->
    <aop:config>
        <!--切点-->
        <aop:pointcut id="mypoint" expression="execution(public void demo04.service.HelloServiceImpl.doSome())"></aop:pointcut>
        <!--<aop:pointcut id="mypoint" expression="execution(* *..service.*.*(..))"></aop:pointcut>-->
        <!--advice-ref:做什么样的配置,是前置还是后置
        pointcut-ref:锁定什么样的方法规则,那个方法需要被锁定
        -->
        <aop:advisor advice-ref="beforeAdvice" pointcut-ref="mypoint"></aop:advisor>
        <aop:advisor advice-ref="afterAdvice" pointcut-ref="mypoint"></aop:advisor>
    </aop:config>
复制代码

测试类

复制代码
import demo04.service.HelloServiceImpl;
import demo04.service.IHelloService;
import demo05.MyCollection;
import demo05.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by mycom on 2018/3/3.
 */
public class Test20180305 {
    @Test
    public void t1(){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContextAop.xml");
        //这里的返回值只能是接口
        IHelloService service =(IHelloService) context.getBean("service");
        service.doSome();

    }


}
复制代码

在这里和要介绍两个单词的意思

  advice :通知
  advisor:顾问

顾问可以包装通知

execution(【modifiers-pattern?】 访问修饰符
ret-type-pattern 返回值类型
【declaring-type-pattern?】 全限定性类名
name-pattern(param-pattern) 方法名(参数名) 包名.类型名.方法名
【throws-pattern?】) 抛出异常类型
public void doLog(String log){

}

方法签名

切入点表达式要匹配的对象就是目标方法的方法名。所以,execution表达式中明显就是方法的签名。
注意:表达式中加[]的部分表示可省略部分,各部分间用空格分开。在其中可以使用以下符号:
符号 意义
* 0至多个任意字符
.. 用在方法参数中,表示任意多个参数
用在包名后,表示当前包及其子包路径
+ 用在类名后,表示当前类及其子类
用在接口后,表示当前接口及其实现类
execution(public * *(..)) 指定切入点为:任意公共方法
execution(* set*(..)) 指定切入点为:任何一个以"set"开始的方法

原文地址:https://www.cnblogs.com/buai/p/8513052.html