标签:
什么是aop:Aspect Oriented Programming的缩写,面向切面编程,通过预编译和动态代理实现程序功能的
统一维护的一种技术
主要功能:日志记录,性能统计,安全控制,事务处理,异常处理等
3.1预编译
-AspectJ 完整的面向切面编程解决方案--》spring不是完整的解决方案,不过spring提供比较好的实现方式,当然spring是同时也是支持这种方式的,这也是一种常用的方式
3.2运行期间动态代理(JDK动态代理,CGLib动态代理)
-SpringAop,JbossAop
Spring的AOP使用纯java实现,无需特殊的编译过程,不需要控制类的加载器层次,目前只支持方法的执行的连接点(通知Spring Bean某个方法执行)
不是为了提供完整AOP实现;而是侧重于一种AOP于IOC容器之间的整合,SpringAOP不会AspectJ(完整的AOP解决方案)竞争
Spring没有使用AspectJ的时候,也可以通过如下方式实现AOP
Spring AOP 默认使用标准的JavaSE动态代理作为AOP代理,这使得任何接口(或者集合)都可以被代理
Spring AOP 中也可以使用CGLIB代理(如果一个业务对象没有实现一个接口)
有接口的:使用JDK的动态里
无接口的:使用CGLIB代理
我们在Java项目开发中,AOP常见的配置有如下3种:
a.基于SpringAOP容器的实现,使用AspectJ(Spring封装了AspectJ的使用),这是一种比较常用的方式,可以很容易看清代码结构
b.运行期间的动态代理实现,这是一种比较老的实现方式,比较繁琐
c.注解实现,这种方式开发起来简单,但是不利于后期维护,比如说很难找出你所有使用了SpringAOP注解的地方
这里我主要介绍第一种,和第二种的使用
<?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-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> <!-- 切面类 --> <bean id="myAspect" class="com.briup.spring.aop.bean.annotation.aop.MyAspect"></bean> <!-- 业务类 --> <bean id="aspectBiz" class="com.briup.spring.aop.bean.annotation.aop.AspectBiz"></bean> <!-- aop配置 可以配置多个--> <aop:config> <!-- 切面类 --> <aop:aspect id="aspectTest" ref="myAspect"> <!-- 切入点 标识切入点 aop包下类名包含Biz的类的所有方法--> <aop:pointcut expression="execution(* com.briup.spring.aop.bean.annotation.aop.*Biz.*(..))" id="myPointcut"/> <!-- 通知 ,通过切入点切入切入切面类中的before方法--> <aop:before method="before" pointcut-ref="myPointcut"/> </aop:aspect> </aop:config> </beans>
/*
* 声明一个切面类
* */
public class MyAspect {
public void before(){
System.out.println("aspect before");
}
}
//业务类
public class AspectBiz {
public void biz(){
System.out.println("Aspect biz");
}
}
@Test
public void aspectBefore(){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("com/briup/spring/chap4/spring-aop-schema-advice.xml");
AspectBiz aspectBiz = (AspectBiz) ac.getBean("aspectBiz");
aspectBiz.biz();
}结果:aspect before Aspect biz
<aop:config> <!-- 切面类 --> <aop:aspect id="aspectTest" ref="myAspect"> <!-- 切入点 标识切入点 aop包下类名以Biz结尾的类的所有方法--> <aop:pointcut expression="execution(* com.briup.spring.aop.bean.annotation.aop.*Biz.*(..))" id="myPointcut"/> <!-- 通知 ,通过切入点切入切入切面类中的before方法 在执行切入点指定的方法之前执行 --> <aop:before method="before" pointcut-ref="myPointcut"/> <!-- 返回之后的通知 --> <aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/> </aop:aspect> </aop:config>切面类:
/*
* 声明一个切面类
* */
public class MyAspect {
public void before(){
System.out.println("aspect before");
}
public void afterReturning(){
System.out.println("aspect afterReturning");
}
}结果:aspect before Aspect biz aspect afterReturning结果可以看出,后置通知会在业务方法的执行之后
<aop:config> <!-- 切面类 --> <aop:aspect id="aspectTest" ref="myAspect"> <!-- 切入点 标识切入点 aop包下类名以Biz结尾的类的所有方法--> <aop:pointcut expression="execution(* com.briup.spring.aop.bean.annotation.aop.*Biz.*(..))" id="myPointcut"/> <!-- 通知 ,通过切入点切入切入切面类中的before方法 在执行切入点指定的方法之前执行 --> <aop:before method="before" pointcut-ref="myPointcut"/> <!-- 返回之后的通知 --> <aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/> <!-- --> <aop:after-throwing method="afteThrowing" pointcut-ref="myPointcut"/> </aop:aspect> </aop:config>切面类:
/*
* 声明一个切面类
* */
public class MyAspect {
public void before(){
System.out.println("aspect before");
}
public void afterReturning(){
System.out.println("aspect afterReturning");
}
public void afteThrowing(){
System.out.println("aspect afteThrowing");
}
}
public void biz(){
System.out.println("Aspect biz");
throw new RuntimeException(); //出现异常的时候afteThrowing才会执行
}aspect before Aspect biz aspect afteThrowing 上边的结果由于抛出异常后,不会正常的返回所有没有aspect afterReturning输出
<aop:config> <!-- 切面类 --> <aop:aspect id="aspectTest" ref="myAspect"> <!-- 切入点 标识切入点 aop包下类名以Biz结尾的类的所有方法--> <aop:pointcut expression="execution(* com.briup.spring.aop.bean.annotation.aop.*Biz.*(..))" id="myPointcut"/> <!-- 通知 ,通过切入点切入切入切面类中的before方法 在执行切入点指定的方法之前执行 --> <aop:before method="before" pointcut-ref="myPointcut"/> <!-- 返回之后的通知 --> <aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/> <!-- --> <aop:after-throwing method="afteThrowing" pointcut-ref="myPointcut"/> <!-- after(finally) advice 不管是否抛出异常,最后都会执行的方法 --> <aop:after method="after" pointcut-ref="myPointcut"/> </aop:aspect> </aop:config>
/*
* 声明一个切面类
* */
public class MyAspect {
public void before(){
System.out.println("aspect before");
}
public void afterReturning(){
System.out.println("aspect afterReturning");
}
public void afteThrowing(){
System.out.println("aspect afteThrowing");
}
public void after(){
System.out.println("aspect after(finally)");
}
}//业务类
public class AspectBiz {
public void biz(){
System.out.println("Aspect biz");
throw new RuntimeException();
}
}测试结果:aspect before Aspect biz aspect afteThrowing aspect after(finally)从结果中可以看出,抛出异常后,切面类中的after方法还是可以执行
如果业务类如下:没有异常,
public class AspectBiz {
public void biz(){
System.out.println("Aspect biz");
}
}结果:aspect before Aspect biz aspect after(finally)
<aop:config> <!-- 切面类 --> <aop:aspect id="aspectTest" ref="myAspect"> <!-- 切入点 标识切入点 aop包下类名以Biz结尾的类的所有方法--> <aop:pointcut expression="execution(* com.briup.spring.aop.bean.annotation.aop.*Biz.*(..))" id="myPointcut"/> <!-- 通知 ,通过切入点切入切入切面类中的before方法 在执行切入点指定的方法之前执行 --> <aop:before method="before" pointcut-ref="myPointcut"/> <!-- 返回之后的通知 --> <aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/> <!-- --> <aop:after-throwing method="afteThrowing" pointcut-ref="myPointcut"/> <!-- after(finally) advice 不管是否抛出异常,最后都会执行的方法 --> <aop:after method="after" pointcut-ref="myPointcut"/> <!-- adroun advice 环绕通知,方法的第一参数必须是ProceedingJoinPoint类型 --> <aop:around method="around" pointcut-ref="myPointcut"/> </aop:aspect> </aop:config>
/*
* 声明一个切面类
* */
public class MyAspect {
public void before(){
System.out.println("aspect before");
}
public void afterReturning(){
System.out.println("aspect afterReturning");
}
public void afteThrowing(){
System.out.println("aspect afteThrowing");
}
public void after(){
System.out.println("aspect after(finally)");
}
public void around(ProceedingJoinPoint joinPoint){
Object object = null;
try{
System.out.println("aspect around 1"); //方法执行前
object = joinPoint.proceed(); //代表业务方法的执行
System.out.println("aspect around 1"); //方法执行后
}catch(Throwable e){
e.printStackTrace();
}
}
}
aspect around 1 Aspect biz aspect around 1
<?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-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> <!-- 切面类 --> <bean id="myAspect" class="com.briup.spring.aop.bean.annotation.aop.MyAspect"></bean> <!-- 业务类 --> <bean id="aspectBiz" class="com.briup.spring.aop.bean.annotation.aop.AspectBiz"></bean> <!-- aop配置 可以配置多个--> <aop:config> <!-- 切面类 --> <aop:aspect id="aspectTest" ref="myAspect"> <!-- 切入点 标识切入点 aop包下类名以Biz结尾的类的所有方法--> <aop:pointcut expression="execution(* com.briup.spring.aop.bean.annotation.aop.*Biz.*(..))" id="myPointcut"/> <!-- 通知 ,通过切入点切入切入切面类中的before方法 在执行切入点指定的方法之前执行 --> <aop:before method="before" pointcut-ref="myPointcut"/> <!-- 返回之后的通知 --> <aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/> <!-- --> <aop:after-throwing method="afteThrowing" pointcut-ref="myPointcut"/> <!-- after(finally) advice 不管是否抛出异常,最后都会执行的方法 --> <aop:after method="after" pointcut-ref="myPointcut"/> <!-- adroun advice 环绕通知,方法的第一参数必须是ProceedingJjoinPoint类型 --> <!-- <aop:around method="around" pointcut-ref="myPointcut"/> --> <!-- 参数传递 --> <aop:around method="aroundInit" pointcut="execution(* com.briup.spring.aop.bean.annotation.aop.AspectBiz.init(String,int)) and args(bizName,times)"/> </aop:aspect> </aop:config> </beans>
/*
* 声明一个切面类
* */
public class MyAspect {
public void before(){
System.out.println("aspect before");
}
public void afterReturning(){
System.out.println("aspect afterReturning");
}
public void afteThrowing(){
System.out.println("aspect afteThrowing");
}
public void after(){
System.out.println("aspect after(finally)");
}
public void around(ProceedingJoinPoint joinPoint){
Object object = null;
try{
System.out.println("aspect around 1"); //方法执行前
object = joinPoint.proceed(); //代表业务方法的执行
System.out.println("aspect around 2"); //方法执行后
}catch(Throwable e){
e.printStackTrace();
}
}
//AOP中参数的传递
public void aroundInit(ProceedingJoinPoint joinPoint,String bizName,int times){
System.out.println(bizName+"--"+times);
Object object = null;
try{
System.out.println("aspect around 1"); //方法执行前
object = joinPoint.proceed(); //代表业务方法的执行
System.out.println("aspect around 1"); //方法执行后
}catch(Throwable e){
e.printStackTrace();
}
}
}public class AspectBiz {
public void biz(){
System.out.println("Aspect biz");
}
public void init(String bizName,int times){
System.out.println("aspectBiz init:"+bizName+" "+times);
}
} @Test
public void aspectAround(){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("com/briup/spring/chap4/spring-aop-schema-advice.xml");
AspectBiz aspectBiz = (AspectBiz) ac.getBean("aspectBiz");
aspectBiz.init("init", 3);
}测试结果:aspect before init--3 aspect around 1 aspectBiz init:init 3 aspect around 1 aspect after(finally) aspect afterReturning AfterClass 标注的方法 会最后执行可以看到,参数比顺利的传送过去
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" 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 name="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation"> <!-- 路径位于src下 --> <value>classpath:hibernate.cfg.xml</value> </property> </bean> <!-- 事物配置 --> <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref local="sessionFactory" /> </property> </bean> <!-- advisor配置 配置事务处理的Bean,定义切面(advice) 由于getxxx,queryxxx,findxxx不涉及事务,可以设置read-only为true --> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="get*" read-only="true" /> <tx:method name="query*" read-only="true" /> <tx:method name="find*" read-only="true" /> <tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Exception" /> <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception" /> <tx:method name="del*" propagation="REQUIRED" rollback-for="java.lang.Exception" /> <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception" /> <tx:method name="*" propagation="REQUIRED" rollback-for="java.lang.Exception" /> </tx:attributes> </tx:advice> <!-- aop配置 --> <aop:config> <!-- 给impl包下的所有的方法配置adivce --> <aop:pointcut expression="excution(* com.briup.spring.aop.bean.annotation.service.impl..(..))" id="serviceMethod" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" /> </aop:config> </beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- 配置委托类 -->
<bean name="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
<!-- 配置代理对象将来执行的时候,所要执行的处理程序 -->
<bean name="advice" class="com.xx.spring.aop.bean.AdviceTest"></bean><!-- advice在方法执行前后添加我们的操作 -->
<!-- 配置代理对象 -->
<bean name="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--proxyInterfaces 如果ProxyFactoryBean的proxyInterfaces属性没有被设置,但是目标类实现类一个或多个接口,
那么ProxyFactoryBean将自动检测到这个目标类已经实现了至少一个接口,创建一个基于JDK的代理 -->
<property name="proxyInterfaces" value="com.xxx.spring.aop.bean.UserDao"></property>
<!-- 注入目标对象(注入被代理的对象) -->
<property name="target" ref="target"></property>
<!-- 注入代理对象所要执行的处理程序,通知配置 -->
<property name="interceptorNames">
<list>
<value>advice</value>
</list>
</property>
</bean>
</beans>
<property name="interfaces">
<array>
<value>com.xxx.spring.aop.bean.UserDao</value>
</array>
</property>
<property name="interceptorNames">
<list>
<value>advice</value>
</list>
</property>
但是 通知是不可以省略的,同时推荐结合的写法import java.util.Date;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class AdviceTest implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation method) throws Throwable {
System.out.println("方法开始执行"+new Date());
method.proceed();
System.out.println("方法执行完毕"+new Date());
return null;
}
}//委托类
public class UserDaoImpl implements UserDao {
@Override
public void saveUser() {
System.out.println("保存用户");
}
@Override
public void deleteUser() {
System.out.println("删除用户");
}
@Override
public void updateUser() {
System.out.println("更新用户");
}
}接口:public interface UserDao {
public abstract void saveUser();
public abstract void deleteUser();
public abstract void updateUser();
}
@Test
public void advice(){
BeanFactory factory = new ClassPathXmlApplicationContext("com/xxx/spring/chap2/advice.xml");
UserDao userDao = factory.getBean("proxy", UserDao.class);
userDao.saveUser();
userDao.deleteUser();
userDao.updateUser();
}测试结果:方法开始执行Sun Sep 11 21:02:12 CST 2016 保存用户 方法执行完毕Sun Sep 11 21:02:12 CST 2016 方法开始执行Sun Sep 11 21:02:12 CST 2016 删除用户 方法执行完毕Sun Sep 11 21:02:12 CST 2016 方法开始执行Sun Sep 11 21:02:12 CST 2016 更新用户 方法执行完毕Sun Sep 11 21:02:12 CST 2016
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- 配置委托类 -->
<bean name="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
<!-- 配置代理对象将来执行的时候,所要执行的处理程序 -->
<bean name="before" class="com.xxx.spring.aop.bean.BeforeTest"></bean>
<!-- 配置代理对象 -->
<bean name="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 注入目标对象(注入被代理的对象) -->
<property name="target" ref="target"></property>
<!-- 注入代理对象需要实现的所有接口 -->
<property name="interfaces">
<array>
<value>com.xxx.spring.aop.bean.UserDao</value>
</array>
</property>
<!-- 注入代理对象所要执行的处理程序 -->
<property name="interceptorNames">
<array>
<value>before</value>
</array>
</property>
</bean>
</beans>import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class BeforeTest implements MethodBeforeAdvice{
@Override
public void before(Method method, Object[] obj, Object object)
throws Throwable {
System.out.println("version 1.0 author tom "+method.getName()+" is execute");
}
}
@Test
public void before(){
BeanFactory factory = new ClassPathXmlApplicationContext("com/xxx/spring/chap2/before.xml");
UserDao userDao = factory.getBean("proxy", UserDao.class);
userDao.saveUser();
userDao.deleteUser();
userDao.updateUser();
}
version 1.0 author tom saveUser is execute 保存用户 version 1.0 author tom deleteUser is execute 删除用户 version 1.0 author tom updateUser is execute 更新用户
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- 配置委托类 -->
<bean name="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
<!-- 配置代理对象将来执行的时候,所要执行的处理程序 -->
<bean name="after" class="com.xxx.spring.aop.bean.AfterTest"></bean>
<!-- 配置代理对象 -->
<bean name="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 注入目标对象(注入被代理的对象) -->
<property name="target" ref="target"></property>
<!-- 注入代理对象需要实现的所有接口 -->
<property name="interfaces">
<array>
<value>com.xxx.spring.aop.bean.UserDao</value>
</array>
</property>
<!-- 注入代理对象所要执行的处理程序 -->
<property name="interceptorNames">
<array>
<value>after</value>
</array>
</property>
</bean>
</beans>import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class AfterTest implements AfterReturningAdvice {
@Override
public void afterReturning(Object arg0, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
System.out.println(arg1.getName()+" is over!");
}
}
测试: @Test
public void after(){
BeanFactory factory = new ClassPathXmlApplicationContext("com/xxx/spring/chap2/after.xml");
UserDao userDao = factory.getBean("proxy", UserDao.class);
userDao.saveUser();
userDao.deleteUser();
userDao.updateUser();
}测试结果:保存用户 saveUser is over! 删除用户 deleteUser is over! 更新用户 updateUser is over!
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- 配置委托类 -->
<bean name="target" class="com.briup.spring.aop.bean.UserDaoImpl"></bean>
<!-- 配置代理对象将来执行的时候,所要执行的处理程序 -->
<bean name="throws" class="com.briup.spring.aop.bean.ThrowsAdiviceTest"></bean>
<!-- 配置代理对象 -->
<bean name="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 注入目标对象(注入被代理的对象) -->
<property name="target" ref="target"></property>
<!-- 注入代理对象需要实现的所有接口 -->
<property name="interfaces">
<array>
<value>com.briup.spring.aop.bean.UserDao</value>
</array>
</property>
<!-- 注入代理对象所要执行的处理程序 -->
<property name="interceptorNames">
<list>
<value>throws</value>
</list>
</property>
</bean>
</beans>import java.lang.reflect.Method;
import org.springframework.aop.ThrowsAdvice;
public class ThrowsAdiviceTest implements ThrowsAdvice{
public void afterThrowing(Method method,Object[] args,Object target,Exception ex)throws Throwable{//Throwable subclass
System.out.println("afterThrowing 2 ...."+method.getName()+" "+ target.getClass().getName());
}
}
@Override
public void saveUser() throws RuntimeException{
System.out.println("保存用户");
throw new RuntimeException();
}
@Test
public void throwTest(){
BeanFactory factory = new ClassPathXmlApplicationContext("com/xxx/spring/chap2/throw.xml");
UserDao userDao = factory.getBean("proxy", UserDao.class);
userDao.saveUser();
userDao.deleteUser();
userDao.updateUser();
}结果:保存用户 afterThrowing 2 ....saveUser com.xxx.spring.aop.bean.UserDaoImpl
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- 配置委托类 -->
<bean name="target" class="com.briup.spring.aop.bean.UserDaoImpl"></bean>
<!-- 配置代理对象将来执行的时候,所要执行的处理程序 -->
<bean name="advice" class="com.briup.spring.aop.bean.AdviceTest"></bean>
<bean name="throws" class="com.briup.spring.aop.bean.ThrowsAdiviceTest"></bean>
<!-- 切入点 -->
<bean name="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedNames">
<list>
<value>sa*</value>
</list>
</property>
</bean>
<!-- advisor -->
<bean id="defaultAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="throws"></property>
<property name="pointcut" ref="pointcutBean"></property>
</bean>
<!-- 配置代理对象 -->
<bean name="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 注入目标对象(注入被代理的对象) -->
<property name="target" ref="target"></property>
<!-- 注入代理对象需要实现的所有接口 -->
<property name="interfaces">
<array>
<value>com.briup.spring.aop.bean.UserDao</value>
</array>
</property>
<!-- 注入代理对象所要执行的处理程序 -->
<property name="interceptorNames">
<list>
<value>defaultAdvisor</value>
<value>throws</value>
</list>
</property>
</bean>
</beans> <!-- 切入点 -->
<bean name="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedNames">
<list>
<value>sa*</value>
</list>
</property>
</bean> <!-- advisor -->
<bean id="defaultAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="advice"></property>
<property name="pointcut" ref="pointcutBean"></property>
</bean><?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- 配置代理对象将来执行的时候,所要执行的处理程序 -->
<bean name="advice" class="com.briup.spring.aop.bean.AdviceTest"></bean>
<bean name="throws" class="com.briup.spring.aop.bean.ThrowsAdiviceTest"></bean>
<!-- 切入点 -->
<bean name="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedNames">
<list>
<value>sa*</value>
</list>
</property>
</bean>
<!-- advisor -->
<bean id="defaultAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="advice"></property>
<property name="pointcut" ref="pointcutBean"></property>
</bean>
<!-- 配置代理对象 -->
<bean name="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 注入目标对象(注入被代理的对象),使用匿名的方式 -->
<property name="target">
<span style="white-space:pre"> </span><bean name="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
</property>
<!-- 注入代理对象需要实现的所有接口 -->
<property name="interfaces">
<array>
<value>com.xxx.spring.aop.bean.UserDao</value>
</array>
</property>
<!-- 注入代理对象所要执行的处理程序 -->
<property name="interceptorNames">
<list>
<value>defaultAdvisor</value>
<value>throws</value>
</list>
</property>
</bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- 配置委托类 -->
<bean name="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
<!-- 配置代理对象将来执行的时候,所要执行的处理程序 -->
<bean name="before" class="com.xxx.spring.aop.bean.BeforeTest"></bean>
<!-- 配置代理对象 -->
<bean name="proxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!-- 注入需要被代理的对象名字,会代理所有以targ开始的bean -->
<property name="beanNames">
<list>
<value>targ*</value>
</list>
</property>
<!-- 注入advice或者advisor -->
<property name="interceptorNames">
<list>
<value>before</value>
</list>
</property>
</bean>
</beans>通过,自动代理,proxy会自动帮我们代理所有以targ开头的目标委托类//委托类
public class UserDaoImpl implements UserDao {
@Override
public void saveUser(){
System.out.println("保存用户");
}
@Override
public void deleteUser() {
System.out.println("删除用户");
}
@Override
public void updateUser() {
System.out.println("更新用户");
}
}
@Test
public void autoAdvisor(){
BeanFactory factory = new ClassPathXmlApplicationContext("com/xxx/spring/chap2/autoAdvisor.xml");
UserDao userDao = factory.getBean("target", UserDao.class);//autoAdvisor只能通过委托类的名字来拿
userDao.saveUser();
userDao.deleteUser();
userDao.updateUser();
}version 1.0 author tom saveUser is execute 保存用户 version 1.0 author tom deleteUser is execute 删除用户 version 1.0 author tom updateUser is execute 更新用户
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- 配置委托类 -->
<bean name="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
<!-- 配置代理对象将来执行的时候,所要执行的处理程序 -->
<bean name="before" class="com.xxx.spring.aop.bean.BeforeTest"></bean>
<!-- 配置advisor -->
<!-- 作用:筛选要拦截的方法 -->
<bean name="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!-- 注入advice -->
<property name="advice" ref="before"></property>
<!-- 注入需要被拦截的目标对象中的方法 -->
<property name="patterns">
<list>
<value>.*deleteUser</value>
</list>
</property>
</bean>
<!-- 配置代理对象,当前IoC容器中自动应用,不用显示应用advisor的bean定义 -->
<bean name="proxy" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
</beans>
@Test
public void autoProxyByName(){
BeanFactory factory = new ClassPathXmlApplicationContext("com/xxx/spring/chap2/autoProxyByName.xml");
UserDao userDao = factory.getBean("target", UserDao.class);
userDao.saveUser();
userDao.deleteUser();
userDao.updateUser();
}保存用户 version 1.0 author tom deleteUser is execute 删除用户 更新用户
标签:
原文地址:http://blog.csdn.net/u014292162/article/details/52504633