Spring AOP面向切面编程
AOP:允许你把遍布应用各处的功能分离出来形成可重用的组件。
比方说,系统中的日志、事务管理。安全服务等,通常会分散到你的每一个组件中,哪怕只是调用某个方法,但他依然会使你的代码变得混乱并且不易修改。某个组件应该只关心如何实现自身的业务逻辑,与其无关的代码(日志,安全等)应该少出现甚至不出现。
AOP使得这些组件具有更高的内聚性以及更加关注与自身业务,完全不需要涉及其他系统服务,甚至你的核心业务根本不知道它们(日志模块,安全模块)的存在。
下面以 演奏者performer为例:
Performer.java
package com.tutorialspoint;
public class Performer {
private Instrument ins;
public Performer(Instrument ins) {
this.ins = ins;
}
public void play() {
ins.play();
}
}
演奏者只关心一件事情就是play(),而具体使用什么乐器,演奏开始与结束时间并不需要 performer 操心。具体演奏的乐器由 Performer 的构造器传入一个继承 Instrument 的类如 Violin。
Instrument.java
package com.tutorialspoint;
public abstract class Instrument {
public Instrument() {
super();
}
abstract void play();
}
Violin.java
package com.tutorialspoint;
public class Violin extends Instrument{
public Violin() {
super();
}
@Override
void play() {
System.out.println("Violin Music!");
}
}
演奏时间由另外的 Record 来记录:
Record.java
package com.tutorialspoint;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Record {
private SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
public void starttime(){
System.out.println(sdf.format(new Date()));
}
public void endtime(){
System.out.println(sdf.format(new Date()));
}
}
类基本书写完毕了,那么如何将Record抽象为切面呢?只需要在配置文件中声明就可以了:
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="performer" class="com.tutorialspoint.Performer">
<constructor-arg ref="violin" />
</bean>
<bean id="violin" class="com.tutorialspoint.Violin"></bean>
<bean id="record" class="com.tutorialspoint.Record"></bean>
<aop:config>
<aop:aspect ref="record">
<aop:pointcut expression="execution(* com.tutorialspoint.Performer.play(..))" id="play"/>
<aop:before method="starttime" pointcut-ref="play"/>
<aop:after method="endtime" pointcut-ref="play"/>
</aop:aspect>
</aop:config>
</beans>
程序入口:
MainAPP.java
package com.tutorialspoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainAPP {
public static void main(String[] args) {
//AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
Performer performer = (Performer) context.getBean("performer");
performer.play();
}
}
程序执行结果:
2018-5-24 17:27:14 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@bf32c: startup date [Thu May 24 17:27:14 CST 2018]; root of context hierarchy
2018-5-24 17:27:14 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [Beans.xml]
18-05-24 17:27:14
Violin Music!
18-05-24 17:27:14
注意!
AOP编程除了需要Spring的包外,还需要以下3个jar包:
aspectjrt.jar
aspectjweaver.jar
aopalliance.jar