您的位置:首页 > 编程语言 > Java开发

第三章 AOP 通过Java API创建增强

2013-07-04 10:21 120 查看


3.3.1增强类型

前置增强:org.springframework.aop.MethodBeforeAdvice
后置增强:org.springframework.aop.AfterReturningAdvice
环绕增强:org.aopalliance.intercept.MethodInterceptor
异常抛出增强:org.springframework.aop.ThrowsAdvice
引介增强:org.springframework.aop.support.DelegatingIntroductionInterceptor

3.3.2前置增强

就是在连接点方法执行之前执行的内容。
如:我们在UserDaoImpl的save()方法执行之前执行一些内容。


a、UserDao与UserDaoImpl:

[java] view
plaincopyprint?

public interface UserDao {    

    public void save();    

}    

[html] view
plaincopyprint?

public class UserDaoImpl implements UserDao {    

    public void save() {    

        System.out.println("保存用户...");    

    }    

}    

b、创建一个增强类实现MethodBeforeAdvice接口
public class UserDaoBeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object object)
throws Throwable {
System.out.println("我是前置增强");
}
}


c、配置
<!-- 把增强类交由spring管理 -->
<bean id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean>

<!-- 把目标类交由spring管理 -->
<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>

<!--
设置代理类
p:target-ref 目标对象
p:proxyInterfaces 代理所要实现的接口,也就是目标对象的接口
p:interceptorNames 织入的增强Bean,可以是多个,用","号分开
-->
<bean id="adviceUserDao"
class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="cn.framelife.spring.dao.UserDao"
p:interceptorNames="userDaoBeforeAdvice"
p:target-ref="userDao"
/>


d、main方法中测试
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
//通过代理来获取userDao对象
UserDao userDao = (UserDao) context.getBean("adviceUserDao");
userDao.save();


f、结果
我是前置增强
保存用户...

3.3.3后置增强

就是在连接点方法执行之后执行的内容。


a、UserDao与UserDaoImpl:

[java] view
plaincopyprint?

public interface UserDao {    

    public void save();    

}    

[html] view
plaincopyprint?

public class UserDaoImpl implements UserDao {    

    public void save() {    

        System.out.println("保存用户...");    

    }    

}    

b、创建一个增强类实现AfterReturningAdvice接口
public class UserDaoAfterAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object object, Method method, Object[] args,
Object arg3) throws Throwable {
System.out.println("我是后置增强");
}
}


c、配置
<bean id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean>
<bean id="userDaoAfterAdvice" class="cn.framelife.spring.advice.UserDaoAfterAdvice"></bean>

<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>

<bean id="adviceUserDao"
class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="cn.framelife.spring.dao.UserDao"
p:interceptorNames="userDaoBeforeAdvice,userDaoAfterAdvice"
p:target-ref="userDao"
/>


d、main方法中测试
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
//通过代理来获取userDao对象
UserDao userDao = (UserDao) context.getBean("adviceUserDao");
userDao.save();


f、结果
保存用户...
我是后置增强


3.3.4环绕增强

环绕增强与struts2的AOP类似。


a、UserDao与UserDaoImpl:

[java] view
plaincopyprint?

public interface UserDao {    

    public void save();    

}    

[html] view
plaincopyprint?

public class UserDaoImpl implements UserDao {    

    public void save() {    

        System.out.println("保存用户...");    

    }    

}    

b、创建一个增强类实现MethodInterceptor接口
public class UserDaoSurroundAdvice implements MethodInterceptor {

@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("环绕增强在方法前执行...");
Object object = invocation.proceed();
System.out.println("环绕增强在方法后执行...");
return object;
}

}


c、配置
<bean id="userDaoSurroundAdvice" class="cn.framelife.spring.advice.UserDaoSurroundAdvice"></bean>

<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>

<bean id="adviceUserDao"
class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="cn.framelife.spring.dao.UserDao"
p:interceptorNames=" userDaoSurroundAdvice"
p:target-ref="userDao"
/>


d、main方法中测试
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
//通过代理来获取userDao对象
UserDao userDao = (UserDao) context.getBean("adviceUserDao");
userDao.save();


f、结果
环绕增强在方法前执行...
保存用户...
环绕增强在方法后执行...


3.3.5异常抛出增强

就是在方法出现异常之后执行的代码。


a、UserDao与UserDaoImpl:

[java] view
plaincopyprint?

public interface UserDao {    

    public void save();    

}    

public class UserDaoImpl implements UserDao {    
    public void save() {    
        System.out.println("保存用户...");    
        //使方法在运行的时候抛出一个异常
         throw new RuntimeException("运行时异常...");

    }    
}  


b、创建一个增强类实现ThrowsAdvice接口
public class UserDaoThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(Method method,Object[] args,Object taglet,Exception ex)throws Throwable{
System.out.println("我是异常抛出接口");
System.out.println(method.getName());
System.out.println(ex.getMessage());
}
}


c、配置
<bean id="userDaoThrowAdvice" class="cn.framelife.spring.advice.UserDaoThrowsAdvice"></bean>

<!--
p:proxyTargetClass="false"
如果目标对象是一个类,而不是一个接口,我们设置为true
-->
<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>

<bean id="adviceUserDao"
class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="cn.framelife.spring.dao.UserDao"
p:interceptorNames="userDaoThrowAdvice"
p:target-ref="userDao"
p:proxyTargetClass="false"
/>


d、main方法中测试
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
//通过代理来获取userDao对象
UserDao userDao = (UserDao) context.getBean("adviceUserDao");
userDao.save();


f、结果
保存用户...
Exception in thread "main" java.lang.RuntimeException: 运行时异常...
at cn.framelife.spring.dao.impl.UserDaoImpl.save(UserDaoImpl.java:12)
at cn.framelife.spring.dao.impl.UserDaoImpl$$FastClassByCGLIB$$18bd6dee.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:688)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:124)我是异常抛出接口
save
运行时异常...

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621)
at cn.framelife.spring.dao.impl.UserDaoImpl$$EnhancerByCGLIB$$5bbe38b0.save(<generated>)
at cn.framelife.spring.test.Test.main(Test.java:17)


3.3.6引介增强

     引介增强是为目标类创建新的方法和属性,引介增强的连接点是类级别的,不是方法级别的。通过引介增强,我们可以为目标类添加一个接口的实现,即原来目标类未实现某个接口,通过引介增强可以为目标类创建实现某个接口的代理。


a、UserDao与UserDaoImpl:

[java] view
plaincopyprint?

public interface UserDao {    

    public void save();    

}    

[html] view
plaincopyprint?

public class UserDaoImpl implements UserDao {    

    public void save() {    

        System.out.println("保存用户...");    

    }    

}    

b、新建一个接口AInterface
public interface AInterface {
public void say();
}


c、增强类继承DelegatingIntroductionInterceptor实现AInterface
public class IntroductionAdvice extends DelegatingIntroductionInterceptor implements AInterface {
/*
* 实现AInterface中的方法
*/
public void say() {
System.out.println("UserDao要说话");
}

/*
* 重写DelegatingIntroductionInterceptor的invoke方法
*/
public Object invoke(MethodInvocation mi) throws Throwable {
System.out.println("方法执行前执行");
System.out.println(mi.getClass().getName());
System.out.println(mi.getMethod().getName());
Object object = super.invoke(mi);
System.out.println("方法执行后执行");
return object;
}
}


d、配置

<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>

<bean id="introductionAdvice" class="cn.framelife.spring.advice.IntroductionAdvice"></bean>
<!--
代理类设置
p:proxyTargetClass="true" 引介增强一定要通过创建子类来生成代理,所以要设置为true。
也不需要配置p:proxyInterfaces目标类的接口
p:interfaces 引介增强所实现的接口
-->
<bean id="aProxy"
class="org.springframework.aop.framework.ProxyFactoryBean"
p:interfaces="cn.framelife.spring.dao.AInterface"
p:interceptorNames="introductionAdvice"
p:target-ref="userDao"
p:proxyTargetClass="true" />


e、main方法中测试
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
UserDao userDao = (UserDao) context.getBean("aProxy");
userDao.save();

System.out.println("-------------");

AInterface a = (AInterface)userDao;
a.say();

System.out.println("-------------");
userDao.save();


f、结果
方法执行前执行
org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation
save
保存用户...
方法执行后执行
-------------
方法执行前执行
org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation
say
UserDao要说话
方法执行后执行
-------------
方法执行前执行
org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation
save
保存用户...
方法执行后执行
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Spring AOP Java API 增强