(1)AOP的起源
来AOP看来,任何的程序都是由服务代码和业务代码组合而成
来AOP看来,程序员应该只关注业务代码,而不要关注服务代码
来AOP看来,程序中所有服务代码交由spring容器搞定,业务代码交由程序员搞定
来AOP看来,业务代码必须要与服务代码共同存在,表面上分隔,但实际上是一个整体
(2)什么是AOP
AOP是一种将业务代码和服务代码分离的设计思想,
但最终通过代理方式整合在一起的技术
(3)AOP能解决什么问题
程序员只关注业务代码,所有的服务代码,都是通过配置的方式解决
(4)AOP思想和本质
思想:分离思想
本质:通过代理实现
(5)OOP与AOP的地位
OOP:它是一个静态概念,OOP还是主流,项目中OOP为主。
AOP:它是一个动态概念,OOP还是支流,项目中AOP为辅。
总之:OOP和AOP是一个互补的技术,不是替代关系
(6)AOP术语
(A)连接点:一个类中所有的业务方法,叫连接点
(B)切入点:一个类中的某业务方法,符合一条件时,该业务方法就是切入点
(C)增强【advice】含有服务代码的类
(D)切面【aspect】:等价于切入点 + 增强
(E)目标对象:有真正业务功能的对象,例如:UserDao
(F)代理对象:是目标对象在非业务功能之外的对象,例如:事务处理,异常信息显示,日志。
二)springAOP中的五种增强类型【UserDao中的addUser()为例】
(A)前置增强【before】
(B)后置增强【after】
如果业务代码出错,后置增强依然会执行
(C)方法返回后增强【after-returning】
如果业务代码出错,方法返回后增强不会执行
(D)方法抛异常后增强【after-throwing】
如果业务代码出错,方法抛异常后增强会执行,反之,不会执行
(E)方法环绕增强【around】
如果业务代码出错,方法环绕增强的后半部份不会执行
三)springAOP开发环境
(1)导入jar包
>>spring.jar/commons-logging.jar
>>aspectjweaver.jar
/aspectjrt.jar/
cglib-nodep-2.1_3.jar
(2)XML声明
(3)execution切入点表达式
参见:<<关于execution表达式中各部分的含义说明.txt>>
<!-- 配置AOP【重点】 -->
<aop:config>
<aop:pointcut
id="xxxx【标识符】"
expression="execution(public void 包名.addUser())"/>(在包名.addUser()中可以省略包名,因为addUser方法是在spring容器中寻找addUser方法)
【表示切入点的条件】
<aop:aspect ref="serviceBeanID">
【表示增强的ID值】
<aop:before method="addUser" pointcut-ref="xxxx"/>
【前置增强】
【执行哪个服务方法】
【引用哪个切入点的条件】
</aop:aspect>
</aop:config>
(4)springAOP的工作过程
(1)启动容器时,创建目标对象和增强对象
(2)<aop:config/>,通过cglib创建代理对象,是目标对象的代理,运行时产生
(3)程序员-代理对象-writeLog()-目标对象-addUser()-代理对象
总结:该过程是spring容器内部完成,使用动态代理技术。
接下来写一个实例认识aop编程:
(1)前置通知类型:
配置文件applicationContext.ml
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- 目标对象 -->
<bean id="userDao" class="com.spring.demo.UserDao"></bean>
<!-- 增强对象 -->
<bean id="serviceBean" class="com.spring.demo.ServiceBean"></bean>
<!-- 前置增强 -->
<aop:config>
<aop:pointcut id="add" expression="execution(public void com.spring.demo.UserDao.addUser())" /><!-- 把连接点变为切入点 -->
<aop:aspect ref="serviceBean">
<aop:before method="writeLog" pointcut-ref="add"/>
</aop:aspect>
</aop:config>
</beans>
两个bean类:UserDao,ServiceBean
package com.spring.demo;
public class UserDao {
public UserDao(){}
public void addUser(){
System.out.println("添加用户");
}
}
package com.spring.demo;
public class ServiceBean {
public ServiceBean(){}
public void writeLog(){
System.out.println("写日志");
}
}
测试类:
package com.spring.demo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext ac=new ClassPathXmlApplicationContext(new String[]{"com/spring/demo/applicationContext.xml"});
UserDao dao= (UserDao) ac.getBean("userDao");
dao.addUser();
}
}
运行结果:
2014-7-10 9:02:05 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@b42cbf: display name [org.springframework.context.support.ClassPathXmlApplicationContext@b42cbf]; startup date [Thu Jul 10 09:02:05 CST 2014]; root of context hierarchy
2014-7-10 9:02:05 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [com/spring/demo/applicationContext.xml]
2014-7-10 9:02:05 org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
信息: Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@b42cbf]: org.springframework.beans.factory.support.DefaultListableBeanFactory@787d6a
2014-7-10 9:02:05 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@787d6a: defining beans [userDao,serviceBean,org.springframework.aop.config.internalAutoProxyCreator,add,org.springframework.aop.aspectj.AspectJPointcutAdvisor#0]; root of factory hierarchy
写日志
添加用户
后置通知:
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- 目标对象 -->
<bean id="userDao" class="com.spring.demo.UserDao"></bean>
<!-- 增强对象 -->
<bean id="serviceBean" class="com.spring.demo.ServiceBean"></bean>
<!-- aop配置 -->
<aop:config>
<aop:pointcut id="add" expression="execution(public void com.spring.demo.UserDao.addUser())" /><!-- 把连接点变为切入点 -->
<aop:aspect ref="serviceBean">
<!--<aop:before method="writeLog" pointcut-ref="add"/> 前置增强 -->
<aop:after method="writeLog" pointcut-ref="add"/><!-- 后置增强 -->
</aop:aspect>
</aop:config>
</beans>
运行结果:
2014-7-10 9:47:47 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6f7ce9: display name [org.springframework.context.support.ClassPathXmlApplicationContext@6f7ce9]; startup date [Thu Jul 10 09:47:47 CST 2014]; root of context hierarchy
2014-7-10 9:47:47 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [com/spring/demo/applicationContext.xml]
2014-7-10 9:47:48 org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
信息: Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@6f7ce9]: org.springframework.beans.factory.support.DefaultListableBeanFactory@1f82982
2014-7-10 9:47:48 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1f82982: defining beans [userDao,serviceBean,org.springframework.aop.config.internalAutoProxyCreator,add,org.springframework.aop.aspectj.AspectJPointcutAdvisor#0]; root of factory hierarchy
添加用户
写日志
(C)方法返回后增强【after-returning】:
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- 目标对象 -->
<bean id="userDao" class="com.spring.demo.UserDao"></bean>
<!-- 增强对象 -->
<bean id="serviceBean" class="com.spring.demo.ServiceBean"></bean>
<!-- aop配置 -->
<aop:config>
<aop:pointcut id="add" expression="execution(public void com.spring.demo.UserDao.addUser())" /><!-- 把连接点变为切入点 -->
<aop:aspect ref="serviceBean">
<!--<aop:before method="writeLog" pointcut-ref="add"/> 前置增强 -->
<!--<aop:after method="writeLog" pointcut-ref="add"/> 后置增强 -->
<aop:after-returning method="writeLog" pointcut-ref="add"/>
</aop:aspect>
</aop:config>
</beans>
E)方法环绕增强【around】
配置文件:
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- 目标对象 -->
<bean id="userDao" class="com.spring.demo.UserDao"></bean>
<!-- 增强对象 -->
<bean id="serviceBean" class="com.spring.demo.ServiceBean"></bean>
<!-- aop配置 -->
<aop:config>
<aop:pointcut id="add" expression="execution(public void com.spring.demo.UserDao.addUser())" /><!-- 把连接点变为切入点 -->
<aop:aspect ref="serviceBean">
<!--<aop:before method="writeLog" pointcut-ref="add"/> 前置增强 -->
<!--<aop:after method="writeLog" pointcut-ref="add"/> 后置增强 -->
<!-- <aop:after-returning method="writeLog" pointcut-ref="add"/> -->
<aop:around method="both" pointcut-ref="add"/>
</aop:aspect>
</aop:config>
</beans>
增强对象的服务方法:
package com.spring.demo;
import org.aspectj.lang.ProceedingJoinPoint;
public class ServiceBean {
public ServiceBean(){}
public void writeLog(){
System.out.println("写日志");
}
public void open(){
System.out.println("打开数据库连接");
}
public void close(){
System.out.println("关闭数据库连接");
}
/**
* 连接目标对象和代理对象的一个桥梁
* @param pj
* @throws Throwable
*/
public void both(ProceedingJoinPoint pj) throws Throwable{
open();
pj.proceed();
close();
}
}
运行结果:2014-7-10 10:19:46 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1960f05: display name [org.springframework.context.support.ClassPathXmlApplicationContext@1960f05]; startup date [Thu Jul 10 10:19:46 CST 2014]; root of context hierarchy
2014-7-10 10:19:46 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [com/spring/demo/applicationContext.xml]
2014-7-10 10:19:46 org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
信息: Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@1960f05]: org.springframework.beans.factory.support.DefaultListableBeanFactory@914f6a
2014-7-10 10:19:46 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@914f6a: defining beans [userDao,serviceBean,org.springframework.aop.config.internalAutoProxyCreator,add,org.springframework.aop.aspectj.AspectJPointcutAdvisor#0]; root of factory hierarchy
打开数据库连接
添加用户
关闭数据库连接