- aspect before
- Aspect biz
- aspect afteThrowing
- 上边的结果因为抛出异常后,不会正常的返回全部没有aspect afterReturning输出
5.1.4最终通知after(finally) advice
无论方法是否会抛出异常都会通知,就像try...catch..finallly
配置文件:
spring-aop-schema-advice.xml
- <aop:config>
- <aop:aspect id="aspectTest" ref="myAspect">
-
- <aop:pointcut expression="execution(* com.xxx.spring.aop.bean.annotation.aop.*Biz.*(..))" id="myPointcut"/>
-
- <aop:before method="before" pointcut-ref="myPointcut"/>
-
- <aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/>
-
- <aop:after-throwing method="afteThrowing" pointcut-ref="myPointcut"/>
-
- <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)
由以上结果能够看到,无论怎么样after方法仍是会执行,很像try...catch..finally
5.1.5环绕通知around
在方法的执行先后执行通知
配置文件:
spring-aop-schema-advice.xml
- <aop:config>
- <aop:aspect id="aspectTest" ref="myAspect">
-
- <aop:pointcut expression="execution(* com.xxx.spring.aop.bean.annotation.aop.*Biz.*(..))" id="myPointcut"/>
-
- <aop:before method="before" pointcut-ref="myPointcut"/>
-
- <aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/>
-
- <aop:after-throwing method="afteThrowing" pointcut-ref="myPointcut"/>
-
- <aop:after method="after" pointcut-ref="myPointcut"/>
-
- <aop:around method="around" pointcut-ref="myPointcut"/>
- </aop:aspect>
- </aop:config>
切面类:
能够看出,环绕方法的第一参数必须四ProceedingJoinPoint类型
- 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
从结果能够看出,joinPoint.proceed其实就是执行业务方法,咱们能够在其以前作和以后作一些操做
5.1.6通知中的参数传递
这里咱们列举环绕通知中的参数参数传递,其余通知也是一样的方式。
配置文件:
spring-aop-schema-advice.xml
- <?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.xxx.spring.aop.bean.annotation.aop.MyAspect"></bean>
-
-
- <bean id="aspectBiz" class="com.xxx.spring.aop.bean.annotation.aop.AspectBiz"></bean>
-
- <aop:config>
-
- <aop:aspect id="aspectTest" ref="myAspect">
-
- <aop:pointcut expression="execution(* com.xxx.spring.aop.bean.annotation.aop.*Biz.*(..))" id="myPointcut"/>
-
- <aop:before method="before" pointcut-ref="myPointcut"/>
-
- <aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/>
-
- <aop:after-throwing method="afteThrowing" pointcut-ref="myPointcut"/>
-
- <aop:after method="after" pointcut-ref="myPointcut"/>
-
-
-
-
- <aop:around method="aroundInit" pointcut="execution(* com.xxx.spring.aop.bean.annotation.aop.AspectBiz.init(String,int))
- and args(bizName,times)"/>
- </aop:aspect>
- </aop:config>
- </beans>
其中,通知中也能够单独指定的pointcut,切入点中,咱们单独指定了init方法,且指定了方法的参数类型,和方法参数的名字,其中方法参数名字,能够更实际的方法参数名字不一样,好比说init(String biz,int t) 都是能够匹配到的,不过为了维护方便,最好仍是都同样。
切面类:
- 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();
- }
- }
-
-
- 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/xxx/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 标注的方法 会最后执行
能够看到,参数比顺利的传送过去
6.Advisor
Advisor就像一个小的自包含,只有一个advice切面经过一个bean标识,而且必须实现一个advice接口,同时advisor也能够很好的利用aspectJ的切入点表达式Spring经过配置文件中 <aop:advisor>元素支持advisor实际使用中,大多数状况下它会和transactional advice配合使用,用于事务控制
配置文件使用案例:
- <?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">
-
- <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:config>
-
- <aop:pointcut expression="excution(* com.xxx.spring.aop.bean.annotation.service.impl..(..))" id="serviceMethod" />
- <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />
- </aop:config>
-
- </beans>
关于spring的事务控制将会在另一篇文章中介绍。
7.SpringAOP代理实现
这种实现方式,主要使用动态代理技术。 有接口的:使用JDK的动态里,无接口的:使用CGLIB代理
这种方式不是很经常使用
7.1.1ProxyFactoryBean
1.使用SpringAOP代理最关键的是使用org.springframework.aop.framework.ProxyFactoryBean,能够彻底控制切入点和通知advice以及他们的顺序
2.使用ProxyFacotryBean或者其余的IOC相关类来建立AOP代理的最重要的好处就是通知切入点能够由IOC来管理
3.被代理的类没有实现任何接口,使用CGLIB代理,否者使用JDK代理
4.经过设置ProxyTargetClass为true能够强制使用CGLIB,(不管是否实现接口)
5.若是目标类实现了一个或者多个接口,那么建立代理的类型将依赖于ProxyFactoryBean的配置
6.若是ProxyFactoryBean的proxyInterfaces属性被设置为一个或者多个全限定接口名,基于JDK的代理被建立
7.若是ProxyFactoryBean的proxyInterfaces属性没有被设置,可是目标类实现类一个或多个接口,那么ProxyFactoryBean将自动检测到这个目标类已经实现了至少一个接口,建立一个基于JDK的代理
7.1.2使用代理实现环绕通知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"
- 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.xxx.spring.aop.bean.AdviceTest"></bean>
-
- <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="proxyInterfaces" value="com.xxx.spring.aop.bean.UserDao">能够不用写,Spring的ProxyFactoryBean将会自动检测到
若是被代理的对象target实现了多个接口能够按照以下配置:
- <property name="interfaces">
- <array>
- <value>com.xxx.spring.aop.bean.UserDao</value>
- </array>
- </property>
value中能够写多个接口
一样:通知interceptorNames若是只用一个通知能够写成<property name="interceptorNames" name="
advice">
若是有多个通知能够写成:
- <property name="interceptorNames">
- <list>
- <value>advice</value>
- </list>
- </property>
可是 通知是不能够省略的,同时推荐结合的写法
上边的委托类即便普通的实现类:即ProxyFactoryBean被代理的对象
<bean name="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
上边的通知配置
<bean name="advice" class="com.briup.spring.aop.bean.AdviceTest"></bean>
ProxyFactoryBean的配置
须要配置被代理的目标对象,通知,目标类实现的接口(能够省略,被ProxyFactoryBean自动识别
)
切面通知实现类
实现MethodInterceptor就能够实现环绕通知,咱们能够在方法的目标对象类的方法执行先后加入处理逻辑
- 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
7.1.3使用动态代理实现前置通知before
配置文件:
- <?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>
切面前置通知实现类:
实现MethodBeforeAdvice
- 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
- 更新用户
7.1.4后置通知afterReturning
配置文件:
- <?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>
切面后置通知:
实现 AfterReturningAdivce接口
- 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!
7.1.5异常通知throw
配置文件:
- <?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="throws" class="com.xxx.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.xxx.spring.aop.bean.UserDao</value>
- </array>
- </property>
-
- <property name="interceptorNames">
- <list>
- <value>throws</value>
- </list>
- </property>
- </bean>
- </beans>
异常通知切面:
参数中必须有Throwable的子类,前边的参数
afterThrowing([Method, args, target], subclassOfThrowable)[]号中的参数可选
- package com.briup.spring.aop.bean;
-
- 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{
- System.out.println("afterThrowing 2 ...."+method.getName()+" "+ target.getClass().getName());
- }
-
- }
测试:
- @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
7.1.6切入点配置pointcut
使用代理方式也能够配置切入点
NameMatchMethodPointcut,根据方法的名字进行匹配
mappedNames匹配的方法名集合
配置文件:
- <?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.xxx.spring.aop.bean.AdviceTest"></bean>
- <bean name="throws" class="com.xxx.spring.aop.bean.ThrowsAdiviceTest"></bean>
-
- <bean name="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
- <property name="mappedNames">
- <list>
- <value>sa*</value>
- </list>
- </property>
- </bean>
-
- <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.xxx.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>
切面:
- <bean id="defaultAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
- <property name="advice" ref="advice"></property>
- <property name="pointcut" ref="pointcutBean"></property>
- </bean>
7.1.7使用匿名的代理对象
使用匿名的代理对象能够将bean的配置到代理里边,这样就不用为target目标对象配置单独的对象,这样能够直接避免目标对象
配置文件:
- <?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.xxx.spring.aop.bean.AdviceTest"></bean>
- <bean name="throws" class="com.xxx.spring.aop.bean.ThrowsAdiviceTest"></bean>
-
- <bean name="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
- <property name="mappedNames">
- <list>
- <value>sa*</value>
- </list>
- </property>
- </bean>
-
- <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">
- <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>
7.1.8IntroductionInterceptor
Introduction是个特别的Advice,能够在不修改代码的基础上添加一些方法,能够参见
http://www.iteedu.com/webtech/j2ee/springdiary/35.php
http://go12345.iteye.com/blog/352745
8.自动代理实现
8.1.BeanNameAutoProxyCreator
Spring容许使用自动代理的bean定义,他能够自动代理选定bean,这样我么就不用为代理对象声明接口,或者没有实现接口的时候,使用CGLIB代理
配置文件:
- <?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">
-
- <property name="beanNames">
- <list>
- <value>targ*</value>
- </list>
- </property>
-
- <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);
- 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
- 更新用户
8.2DefaultAdvisorAutoProxyCreator
使用DefaultAdvisorAutoProxyCreator咱们能够不用显示的指定advisor的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="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
-
- <bean name="before" class="com.xxx.spring.aop.bean.BeforeTest"></bean>
-
-
- <bean name="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
-
- <property name="advice" ref="before"></property>
-
- <property name="patterns">
- <list>
- <value>.*deleteUser</value>
- </list>
- </property>
- </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
- 删除用户
- 更新用户