IOC:
AOP:横向重复,纵向抽取
体现:servlet中的Filter(解决乱码问题)
xxxService中使用动态代理InvocationHandler(事务管理)
Action中的拦截器(参数赋值)
spring的AOP名次解释:
spring的AOP需要的jar
spring的AOP代码部分
UserService.java
package cn.itcast.service; public interface UserService { void save(); void delete(); void update(); void find(); }
UserServiceImpl.java
package cn.itcast.service; public class UserServiceImpl implements UserService { @Override public void save() { System.out.println("保存用户!"); //int i = 1/0; } @Override public void delete() { System.out.println("删除用户!"); } @Override public void update() { System.out.println("更新用户!"); } @Override public void find() { System.out.println("查找用户!"); } }
----------------------------spring的AOP XML配置----------------------------
MyAdvice.java 通知类
package cn.itcast.d_springaop; import org.aspectj.lang.ProceedingJoinPoint; public class MyAdvice { //前置通知 // |-目标方法之前调用 //后置通知(如果出现异常不会调用) // |-在目标方法运行之后调用 //环绕通知 // |-在目标方法之前和之后调用 //异常拦截通知 // |-如果出现异常,就会调用 //后置通知(无论是否出现异常都会调用) // |-在目标方法运行之后调用 //------------------------------------ //前置通知 public void beforeAdvice(){ System.out.println("这是前置通知!"); } //后置通知(如果出现异常不会调用) public void afterAdvice(){ System.out.println("这是后置通知,(出现异常不调用)!"); } //环绕通知 public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("这是环绕通知之前的部分!"); Object proceed = pjp.proceed();//调用目标方法 System.out.println("这是环绕通知之后的部分!"); return proceed; } //异常拦截通知 public void exceptionAdvice(){ System.out.println("这是异常通知,出现异常了!"); } //后置通知(无论是否出现异常都会调用) public void afterEnhanceAdvice(){ System.out.println("这是后置通知,(不管是否出现异常都调用)!"); } }
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd "> <!-- 准备工作: 导入aop(约束)命名空间 --> <!-- 1.配置目标对象 --> <bean name="userService" class="cn.itcast.service.UserServiceImpl" ></bean> <!-- 2.配置通知对象 --> <bean name="myAdvice" class="cn.itcast.d_springaop.MyAdvice" ></bean> <!-- 3.配置将通知织入目标对象 --> <aop:config> <!-- 配置切入点的演化过程 public void cn.itcast.service.UserServiceImpl.save() void cn.itcast.service.UserServiceImpl.save() * cn.itcast.service.UserServiceImpl.save() * cn.itcast.service.UserServiceImpl.*() * cn.itcast.service.*ServiceImpl.*(..) * cn.itcast.service..*ServiceImpl.*(..) //从cn.itcast.service(包以及子包下..)找(所有以ServiceImpl结尾的类*)当中的(所有方法.*)(参数不做任何限制..)并且(返回值任意*) --> <aop:pointcut expression="execution(* cn.itcast.service.*ServiceImpl.*(..))" id="pc"/> <aop:aspect ref="myAdvice" > <!-- 指定名为beforeAdvice方法作为前置通知 --> <aop:before method="beforeAdvice" pointcut-ref="pc" /> <!-- 后置 --> <aop:after-returning method="afterAdvice" pointcut-ref="pc" /> <!-- 环绕通知 --> <aop:around method="aroundAdvice" pointcut-ref="pc" /> <!-- 异常拦截通知 --> <aop:after-throwing method="exceptionAdvice" pointcut-ref="pc"/> <!-- 后置 --> <aop:after method="afterEnhanceAdvice" pointcut-ref="pc"/> </aop:aspect> </aop:config> </beans>
----------------------------spring的AOP 注解配置----------------------------
MyAdvice.java
package cn.itcast.e_annotationaop; 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; @Aspect public class MyAdvice { //前置通知 // |-目标方法之前调用 //后置通知(如果出现异常不会调用) // |-在目标方法运行之后调用 //环绕通知 // |-在目标方法之前和之后调用 //异常拦截通知 // |-如果出现异常,就会调用 //后置通知(无论是否出现异常都会调用) // |-在目标方法运行之后调用 //------------------------------------ @Pointcut("execution(* cn.itcast.service.*ServiceImpl.*(..))")//制定切点的第二种方式 public void pc(){} //前置通知 //指定该方法是前置通知,并制定切入点 //@Before("execution(* cn.itcast.service.*ServiceImpl.*(..))")//制定切点的第一种方式 @Before("MyAdvice.pc()")//制定切点的第二种方式 public void beforeAdvice(){ System.out.println("这是前置通知!"); } //后置通知(如果出现异常不会调用) //@AfterReturning("execution(* cn.itcast.service.*ServiceImpl.*(..))")//制定切点的第一种方式 @AfterReturning("MyAdvice.pc()")//制定切点的第二种方式 public void afterAdvice(){ System.out.println("这是后置通知,(出现异常不调用)!"); } //环绕通知 //@Around("execution(* cn.itcast.service.*ServiceImpl.*(..))")//制定切点的第一种方式 @Around("MyAdvice.pc()")//制定切点的第二种方式 public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("这是环绕通知之前的部分!"); Object proceed = pjp.proceed();//调用目标方法 System.out.println("这是环绕通知之后的部分!"); return proceed; } //异常拦截通知 //@AfterThrowing("execution(* cn.itcast.service.*ServiceImpl.*(..))")//制定切点的第一种方式 @AfterThrowing("MyAdvice.pc()")//制定切点的第二种方式 public void exceptionAdvice(){ System.out.println("这是异常通知,出现异常了!"); } //后置通知(无论是否出现异常都会调用) //@After("execution(* cn.itcast.service.*ServiceImpl.*(..))")//制定切点的第一种方式 @After("MyAdvice.pc()")//制定切点的第二种方式 public void afterEnhanceAdvice(){ System.out.println("这是后置通知,(不管是否出现异常都调用)!"); } }
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd "> <!-- 准备工作: 导入aop(约束)命名空间 --> <!-- 1.配置目标对象 --> <bean name="userService" class="cn.itcast.service.UserServiceImpl" ></bean> <!-- 2.配置通知对象 --> <bean name="myAdvice" class="cn.itcast.d_springaop.MyAdvice" ></bean> <!-- 3.开启使用注解完成织入 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
Demo.java测试类
package cn.itcast.b_test; import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import cn.itcast.bean.User; import cn.itcast.service.UserService; //帮我们创建容器 @RunWith(SpringJUnit4ClassRunner.class) //指定创建容器时使用哪个配置文件 @ContextConfiguration("classpath:cn/itcast/d_springaop/applicationContext.xml")//测试xml配置AOP //@ContextConfiguration("classpath:cn/itcast/d_springaop/applicationContext.xml")//测试注解配置AOP public class Demo { //将名为user的对象注入到u变量中 @Resource(name="userService") private UserService us; @Test public void fun1(){ us.save(); } }