一.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