一:目标类 Seller.java
package aopAspectj;
public class Seller {
public void sellerBefore(){
System.out.println("in seller sellerBefore run");
}
public void sellerBeforeParam(String name){
System.out.println("in seller sellerBeforeParma run--->"+name);
}
public void sellerCommonMethod(String name){
System.out.println("in seller commonMethod run--->"+name);
}
public void sellerAfter(){
System.out.println("in seller sellerAfter run");
}
public void sellerAfterThrowing() throws Exception{
System.out.println("in seller sellerAfterThrowing run");
throw new Exception("exception");
}
public String sellerAfterReturn(String name){
System.out.println("in seller sellerReturn run--->"+name);
return name;
}
public void sellerAround(){
System.out.println("in seller sellerAround run");
}
}
二:切面类(增强)
package aopAspectj;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.hibernate.annotations.Target;
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
/**
* 通过注解定义一个切面。 通过@Aspect注解定义advisor时,没有继承任何类和实现任何接口,我们在
* advisor包中配置的两个切面都实现了接口,只不过regexp切面 本身的
* 功能已经很完善,没有对齐进行扩展,而StaticMethodMatcherPointcutAdvisor切面我们定义了一个扩展类
*
* 所有的增强方法都可以加入入参 JointPoint 用以获得链接点信息,around增强比较特殊,是ProceedingJoinPoint
* @author majian
*
*/
@Aspect
public class AspectjAdvisor {
/**
* "*" 代表单个元素,(一个单词,或一个字母,".." 表示任意个元素) 任意公共方法的执行: execution(public * *(..))
* 任何一个名字以“set”开始的方法的执行: execution(* set*(..)) AccountService接口定义的任意方法的执行:
* execution(* com.xyz.service.AccountService.*(..)) 在service包中定义的任意方法的执行:
* execution(* com.xyz.service.*.*(..)) 在service包或其子包中定义的任意方法的执行:
* execution(* com.xyz.service..*.*(..))
* */
/**###################################################*/
/**before 不带参数的前置增强*/
@Before(value="execution(* sellerBefore(..))")
public void beforeAdvisor(){
System.out.println("in advisor beforeAdvisor");
}
/** before 带参数的前置增强,参数要与目标类中要调用的方法名相同,多个参数用逗号隔开*/
@Before(value = "execution(* sellerBeforeParam(..)) && args(name)", argNames = "name")
public void beforeAdvisorParam(String name) {
System.out.println("in advisor beforeAdvisorParam--->" + name);
}
/**
* 在每一个advice方法中都配置切点表达式过于麻烦,可以标注一个公共的切点函数,
* 用以描述切点信息,没有返回值,只做标注使用,其他的标注了@befor,@afterreturning等的方法 就可以在value属性中直接调用了
* */
@Pointcut(value = "execution(* sellerCommonMethod(..)) && args(name)", argNames = "name")
public void markMethod(String name) {
}
/** 调用上面统一的切点表达式 */
@Before(value = "markMethod(name)", argNames = "name")
public void commonMethod(String name) {
System.out.println("in advisor commonMethod--->" + name);
}
/**after增强*/
@After(value="execution(* sellerAfter(..))")
public void afterAdvisor(){
System.out.println("in advisor afterAdvisor");
}
/**afterThrowing 抛出异常增强*/
@AfterThrowing(value="execution(* sellerAfterThrowing(..))",throwing="exception")
public void afterThrowingAdvisor(Exception exception ){
System.out.println("in advisor afterThrowingAdvisor--->"+exception);
}
/** #################################################################### **/
/**
* 后置返回增强
*
* @AfterReturning( value="切入点表达式或命名切入点",
* pointcut="和value同义,会覆盖value",
* argNames="参数列表参数名",
* returning="目标方法的返回值")
*
* */
@AfterReturning(value="execution(* sellerAfterReturn(..))",
argNames="name",returning="name")//目标方法加一个入参会怎样?
public void afterReturn(String name) {
System.out.println("in advisor afterReturn--->"+name);
}
/**around 增强,这个比较特殊,
* @throws Throwable */
@Around(value="execution(* sellerAround(..))")
public Object aroundAdvisor(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("in advisor aroundAdvisor before");
Object retVal = pjp.proceed(new Object[] {});
System.out.println("in advisor aroundAdvisor end");
return retVal;
}
}
三:IOC容器配置文件(这里配置了俩个,为了把不同的功能分开,看的更清楚)也可以用注解的方式
applicationContext1.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:jaxws="http://cxf.apache.org/jaxws"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:component-scan base-package="dao,model,service,client,advice" />
<!--目标bean -->
<bean id="seller" class="aopAspectj.Seller"></bean>
<!--使用了aspectj注解的切面类 -->
<bean class="aopAspectj.AspectjAdvisor"></bean>
<!--自动代理创建器,自动将标注了 @aspectj注解的切面类 植入目标bean中-->
<!--引入了aop命名空间的话可以用 <aop:aspectj-autoproxy />代替 -->
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"></bean>
</beans>
applicationContext2.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:jaxws="http://cxf.apache.org/jaxws"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
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-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:component-scan base-package="dao,model,service,client,advice" />
<!--基于aop的aspectj的配置方式 .下面aop标签有个 proxy-target-class为false表示使用jdk的动态代理进行 植入增强-->
<aop:aspectj-autoproxy proxy-target-class="true" />
<!--目标bean -->
<bean id="seller" class="aopAspectj.Seller"></bean>
<!--使用了aspectj注解的切面类 -->
<bean class="aopAspectj.AspectjAdvisor"></bean>
</beans>
三:测试类
package aopAspectj;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AspectjTest {
/**before 代码的方式生成目标类的代理*/
@Test
public void test1() {
Seller Seller = new Seller();
// aspectj工厂
AspectJProxyFactory factory = new AspectJProxyFactory();
// 设置目标对象
factory.setTarget(Seller);
// 添加切面类 此处的切面类AspectjAdvisor必须是标注了@aspectj注解的切面类
factory.addAspect(AspectjAdvisor.class);
// 生成植入切面的代理对象
Seller proxy = factory.getProxy();
proxy.sellerBeforeParam("zhangsan");
}
/**before 配置文件的方式*/
@Test
public void test2() {
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext1.xml");
Seller Seller=(Seller)context.getBean("seller");
Seller.sellerBeforeParam("zhangsan");
}
/**before 使用aop命名空间的配置(就是不用配置自动代理bean了,以一个aop元素代替了)*/
@Test
public void test3(){
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerBeforeParam("zhangsan");
}
/**before 不在@before(value="")中配置切点,而是把切点配置在一个公共的标记方法中,其他标注了@before,@around
*的切点注解中,再value属性中直接调用这个方法
* */
@Test
public void test4(){
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerCommonMethod("zhangsan");
}
/**before 不带参数 advice增强*/
@Test
public void test5(){
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerBefore();
}
/**before 带参数的advice增强*/
@Test
public void test6(){
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerBeforeParam("zhangsan");
}
/**after增强*/
@Test
public void test7(){
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerAfter();
}
/**afterThrowing增强
* @throws Exception */
@Test
public void test8() throws Exception{
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerAfterThrowing();
}
/**afterReturn 增强*/
@Test
public void test9(){
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerAfterReturn("lisi");
}
/**around 增强*/
@Test
public void test10(){
ApplicationContext context=new ClassPathXmlApplicationContext("aopAspectj/applicationContext2.xml");
Seller seller=(Seller)context.getBean("seller");
seller.sellerAround();
}
}