Java——面向切面编程,Spring中的AOP编程
面向切面编程
AOP思想:将横向重复代码,纵向抽取出来
AOP体现——Filter
AOP体现——拦截器
AOP体现——动态代理
Spring中实现AOP思想
原理:Spring可以为容器中管理的对象生成代理对象
代理分为动态代理和cglib代理:
- 动态代理(优先)
- 被代理对象必须要实现接口,才能产生代理对象,如果没有接口将不能使用动态代理技术,换句话说,就是代理对象和被代理要实现同一接口
- cglib代理
- 第三方代理技术,cglib代理,可以对任何类生成代理,代理的原理是对目标对象进行继承代理,如果目标对象被final修饰,那么该类无法被cglib代理
- Hibernate的实体使用的是cglib代理
名次解释
代码实现:
1) 导包
4+2
spring-aop-4.2.4.RELEASE.jar
spring-aspects-4.2.4.RELEASE.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
2)准备接口和实现类
UserService接口
public interface UserService { void save(); void delete(); void update(); void find(); }
UserServiceImpl实现类
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("查找用户!"); } }
3)准备通知(要往里面织入的代码)
//通知类 public class MyAdvice { //前置通知 public void before(){ System.out.println("这是前置通知!!"); } //后置通知 public void afterReturning(){ System.out.println("这是后置通知(如果出现异常不会调用)!!"); } //环绕通知 public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("这是环绕通知之前的部分!!"); Object proceed = pjp.proceed();//调用目标方法 System.out.println("这是环绕通知之后的部分!!"); return proceed; } //异常通知 public void afterException(){ System.out.println("出事啦!出现异常了!!"); } //后置通知 public void after(){ System.out.println("这是后置通知(出现异常也会调用)!!"); } }
4)配置进行织入,将通知织入目标对象中
<?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 "> <!--1.配置目标对象--> <bean name="userService" class="cn.x5456.service.impl.UserServiceImpl"></bean> <!--2.配置通知对象--> <bean name="myAdvice" class="cn.x5456.advice.MyAdvice"></bean> <!--3.配置织入点--> <aop:config> <!--id任意,配置切点--> <aop:pointcut id="pc" expression="execution(* cn.x5456.service.impl.*ServiceImpl.*(..))"></aop:pointcut> <!--配置通知,ref是通知的类名--> <aop:aspect ref="myAdvice"> <!--method与通知对象中的方法名对应,pointcut为织入点的id--> <!-- 指定名为before方法作为前置通知 --> <aop:before method="before" pointcut-ref="pc" /> <!-- 后置 --> <aop:after-returning method="afterReturning" pointcut-ref="pc" /> <!-- 环绕通知 --> <aop:around method="around" pointcut-ref="pc" /> <!-- 异常拦截通知 --> <aop:after-throwing method="afterException" pointcut-ref="pc"/> <!-- 后置 --> <aop:after method="after" pointcut-ref="pc"/> </aop:aspect> </aop:config> </beans>
5)测试类
public class testDemo { @Test public void func(){ ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml"); UserService userService = (UserService) ac.getBean("userService"); userService.save(); } }