Spring 学习记录
入门二:AOP面向方面编程使用
1.1 导入相关JAR包
1.1.1 spring 包
spring-aop-3.2.2.RELEASE.jar
spring-context-3.2.2.RELEASE.jar
spring-expression-3.2.2.RELEASE.jar (如果不加这个包,在编译时通过,运行时报错:
Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/expression/PropertyAccessor
at org.springframework.context.support.AbstractApplicationContext.prepareBeanFactory(AbstractApplicationContext.java:553)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:454)
at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:140)
at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:84)
at cuigh.spring.aop.hello.ProxyFactoryBeanExample.main(ProxyFactoryBeanExample.java:15)
Caused by: java.lang.ClassNotFoundException: org.springframework.expression.PropertyAccessor
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
)
下面这个不在下载包spring-framework-3.2.2.RELEASE-dist 中,需要另外找,在
spring-framework-2.0.6-with-dependencies包中有。
aopalliance.jar
2 项目内容
说明:SPING的第二个功能,AOP(Aspect Oriented Programming,面向方面编程)
2.1 需求:对数据操作前做日志处理
2.1.1 所有方法在执行前做日志处理
2.1.2 只对save开头的方法在执行前做日志处理
2.2 相关程序
2.2.1 业务逻辑类:MyBean.java
2.2.2 业务实现类,对数据库时行操作:DbProcess.java
2.2.3 spring配置文件 : hello-aop.xml
2.2.4 通知类:LogBeforeSave.java
2.2.5 演示类:ProxyFactoryBeanExample.java
3 实现代码
3.1 业务逻辑类:MyBean.java
package cuigh.spring.aop.hello;
/*
* 功能:业务逻辑类
* */
public class MyBean {
private DbProcess dbProcess;
/*
* 功能;执行数据库操作
* */
public void execute(){
dbProcess.save();
dbProcess.query();
dbProcess.saveSecond();
}
/*
* 功能:采用set注入依赖
* */
public void setDep(DbProcess dbProcess){
this.dbProcess=dbProcess;
}
}
3.2 业务实现类,对数据库时行操作:DbProcess.java
package cuigh.spring.aop.hello;
/*
* 功能:业务实现类,对数据库时行操作
* */
public class DbProcess {
/*
* 功能:保存数据
*
* */
public void save(){
System.out.println("保存数据方法 save()");
}
/*
* 功能:保存数据
*
* */
public void saveSecond(){
System.out.println("保存数据方法 saveSecond()");
}
/*
* 功能:查询数据
* */
public void query(){
System.out.println("查询数据方法query()");
}
}
3.3 spring配置文件 : hello-aop.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 声明性AOP设置 -->
<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-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<bean id="myBean1" class="cuigh.spring.aop.hello.MyBean">
<property name="dep">
<ref local="DbProcess1"/>
</property>
</bean>
<bean id="myBean2" class="cuigh.spring.aop.hello.MyBean">
<property name="dep">
<ref local="DbProcess2"/>
</property>
</bean>
<bean id="DbProcessTarget" class="cuigh.spring.aop.hello.DbProcess"/>
<!-- 直接使用通知来通知目标,所有方法都会收到通知 -->
<bean id="DbProcess1" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="DbProcessTarget" />
</property>
<property name="interceptorNames">
<list>
<value>advice</value> <!-- 此处不一样 -->
</list>
</property>
</bean>
<!-- 1 定义切入点pointcut JdkRegexpMethodPointcut
2 配置匹配模式 <value>.*save.*</value>,即只有save方法才会收到通知
-->
<bean id="DbProcess2" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="DbProcessTarget" />
</property>
<property name="interceptorNames">
<list>
<value>advisor</value> <!-- 此处不一样 -->
</list>
</property>
</bean>
<bean id="advice" class="cuigh.spring.aop.hello.LogBeforeSave" />
<bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice">
<ref local="advice" />
</property>
<property name="pointcut">
<bean class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern">
<value>.*save.*</value>
</property>
</bean>
</property>
</bean>
</beans>
3.4 通知类:LogBeforeSave.java
package cuigh.spring.aop.hello;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
/*
* 功能:在数据保存到数据库前做日志处理
*
* */
public class LogBeforeSave implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println("方法执行前log处理,执行方法名="+method.getName());
}
}
3.5 演示类:ProxyFactoryBeanExample.java
package cuigh.spring.aop.hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class ProxyFactoryBeanExample {
/**
* 功能:演示切面使用
*/
public static void main(String[] args) {
String xmlFile = System.getProperty("user.dir")+"\\bin\\cuigh\\spring\\aop\\hello\\"
+"hello-aop.xml";
ApplicationContext ctx = new FileSystemXmlApplicationContext(xmlFile);
MyBean bean1 = (MyBean)ctx.getBean("myBean1");
MyBean bean2 = (MyBean)ctx.getBean("myBean2");
System.out.println("对方法 save query 做日志处理");
bean1.execute();
System.out.println("------------------------------------------------------");
System.out.println("只对方法save 做日志处理");
bean2.execute();
}
}
程序输出:
对方法 save query 做日志处理
方法执行前log处理,执行方法名=save
保存数据方法 save()
方法执行前log处理,执行方法名=query
查询数据方法query()
方法执行前log处理,执行方法名=saveSecond
保存数据方法 saveSecond()
------------------------------------------------------
只对方法save 做日志处理
方法执行前log处理,执行方法名=save
保存数据方法 save()
查询数据方法query()
方法执行前log处理,执行方法名=saveSecond
保存数据方法 saveSecond()