AOP 面向切面,可以让我们在不修改业务代码的前提下,在业务代码执行前后进行执行相应的模块,这样,我们就可以把诸如日志的功能模块合核心业务模块分隔开来,以往的的日志做法都是由核心模块主动的调用日志记录功能,耦合性很强,使用AOP技术,可以将日志模块作为切面,插入到核心业务前执行,核心业务并不主动的调用日志记录功能
本例中使用GreetingHelloworldImpl代表核心业务模块,使用LoggerService代表作为aop实现的日志模块
核心业务并没有主动依赖日志模块
package
SimpleAOPTest;
public interface GreetingHelloworld ... {
public void sayHelloworld();
}
package SimpleAOPTest;
public class GreetingHelloworldImpl implements GreetingHelloworld ... {
private String greetingText;
private String greetingFromConstructor;
public GreetingHelloworldImpl(String greetingFromConstructor)...{
this.greetingFromConstructor=greetingFromConstructor;
}
public GreetingHelloworldImpl()...{
}
public String getGreetingText() ...{
return greetingText;
}
public void setGreetingText(String greetingText) ...{
this.greetingText = greetingText;
}
public void sayHelloworld() ...{
System.out.println(this.getGreetingText());
System.out.println(this.getGreetingFromConstructor());
}
public String getGreetingFromConstructor() ...{
return greetingFromConstructor;
}
public void setGreetingFromConstructor(String greetingFromConstructor) ...{
this.greetingFromConstructor = greetingFromConstructor;
}
}
public interface GreetingHelloworld ... {
public void sayHelloworld();
}
package SimpleAOPTest;
public class GreetingHelloworldImpl implements GreetingHelloworld ... {
private String greetingText;
private String greetingFromConstructor;
public GreetingHelloworldImpl(String greetingFromConstructor)...{
this.greetingFromConstructor=greetingFromConstructor;
}
public GreetingHelloworldImpl()...{
}
public String getGreetingText() ...{
return greetingText;
}
public void setGreetingText(String greetingText) ...{
this.greetingText = greetingText;
}
public void sayHelloworld() ...{
System.out.println(this.getGreetingText());
System.out.println(this.getGreetingFromConstructor());
}
public String getGreetingFromConstructor() ...{
return greetingFromConstructor;
}
public void setGreetingFromConstructor(String greetingFromConstructor) ...{
this.greetingFromConstructor = greetingFromConstructor;
}
}
日志模块:
package
SimpleAOPTest;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class LoggerService implements MethodBeforeAdvice ... {
public LoggerService()...{
}
public void before(Method method, Object[] obj, Object target)
throws Throwable ...{
System.out.println("this is info from LoggerService");
}
}
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class LoggerService implements MethodBeforeAdvice ... {
public LoggerService()...{
}
public void before(Method method, Object[] obj, Object target)
throws Throwable ...{
System.out.println("this is info from LoggerService");
}
}
配置文件:
<?
xml version="1.0" encoding="UTF-8"
?>
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
< beans >
< bean id ="greetingTarget" class ="SimpleAOPTest.GreetingHelloworldImpl" >
< constructor-arg >
< value > this is helloworld from construtor </ value >
</ constructor-arg >
< property name ="greetingText" >
< value > hello world! </ value >
</ property >
</ bean >
< bean id ="loggerService" class ="SimpleAOPTest.LoggerService" ></ bean >
< bean id ="greeting" class ="org.springframework.aop.framework.ProxyFactoryBean" >
< property name ="proxyInterfaces" >
< list >
< value > SimpleAOPTest.GreetingHelloworld </ value > <!-- 拦截GreetingHelloworld接口中的方法 -->
</ list >
</ property >
< property name ="interceptorNames" >
< list >
< value > loggerService </ value > <!-- 处理loggerService请求,切入 -->
</ list >
</ property >
< property name ="target" >
< ref bean ="greetingTarget" /> <!-- 然后处理greeting请求 -->
</ property >
<!-- 代理目标为类时设置
<property name="proxyTargetClass">
<value>true</value>
</property>
-->
</ bean >
</ beans >
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
< beans >
< bean id ="greetingTarget" class ="SimpleAOPTest.GreetingHelloworldImpl" >
< constructor-arg >
< value > this is helloworld from construtor </ value >
</ constructor-arg >
< property name ="greetingText" >
< value > hello world! </ value >
</ property >
</ bean >
< bean id ="loggerService" class ="SimpleAOPTest.LoggerService" ></ bean >
< bean id ="greeting" class ="org.springframework.aop.framework.ProxyFactoryBean" >
< property name ="proxyInterfaces" >
< list >
< value > SimpleAOPTest.GreetingHelloworld </ value > <!-- 拦截GreetingHelloworld接口中的方法 -->
</ list >
</ property >
< property name ="interceptorNames" >
< list >
< value > loggerService </ value > <!-- 处理loggerService请求,切入 -->
</ list >
</ property >
< property name ="target" >
< ref bean ="greetingTarget" /> <!-- 然后处理greeting请求 -->
</ property >
<!-- 代理目标为类时设置
<property name="proxyTargetClass">
<value>true</value>
</property>
-->
</ bean >
</ beans >
测试代码:
package
SimpleAOPTest;
import java.io.File;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
public class TestHelloWorld ... {
public static void main(String[] args) ...{
String filePath=System.getProperty("user.dir")+File.separator+"SimpleAOPTest"+File.separator+"hello.xml";
BeanFactory factory=new XmlBeanFactory(new FileSystemResource(filePath));
//代理目标为接口时使用
GreetingHelloworld greetingSerview=(GreetingHelloworld)factory.getBean("greeting");
//代理目标为类是使用,并配置xml中proxyTargetClass,需要CGLIB包
//<property name="proxyTargetClass">
//<value>true</value>
//</property>
//GreetingHelloworldImpl greetingSerview=(GreetingHelloworldImpl)factory.getBean("greeting");
greetingSerview.sayHelloworld();
}
// public static String getRealPath(String filename){
// String path="";
// Class theClass=TestHelloWorld.class;
// java.net.URL u= theClass.getResource(filename);
// return u.getPath();
//
//
// }
}
import java.io.File;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
public class TestHelloWorld ... {
public static void main(String[] args) ...{
String filePath=System.getProperty("user.dir")+File.separator+"SimpleAOPTest"+File.separator+"hello.xml";
BeanFactory factory=new XmlBeanFactory(new FileSystemResource(filePath));
//代理目标为接口时使用
GreetingHelloworld greetingSerview=(GreetingHelloworld)factory.getBean("greeting");
//代理目标为类是使用,并配置xml中proxyTargetClass,需要CGLIB包
//<property name="proxyTargetClass">
//<value>true</value>
//</property>
//GreetingHelloworldImpl greetingSerview=(GreetingHelloworldImpl)factory.getBean("greeting");
greetingSerview.sayHelloworld();
}
// public static String getRealPath(String filename){
// String path="";
// Class theClass=TestHelloWorld.class;
// java.net.URL u= theClass.getResource(filename);
// return u.getPath();
//
//
// }
}
运行结果:
2007-5-14 23:13:47 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from file [E:/项目/SpringInActionStudy/SimpleAOPTest/hello.xml]
this is info from LoggerService
hello world!
this is helloworld from construtor
可以看到,日志模块打印的信息“this is info from LoggerService”在核心业务运行之前执行了,这样,我们就算对日至模块进行天翻地覆的变化,都不会影响我们的核心业务