spring整合junit测试: 1.导包aop+test 2.@RunWith(SpringJUnit4ClassRunner.class)//帮我们创建容器 @ContextConfiguration("classpath:applicationContext.xml")//指定创建容器时使用那个配置文件 public class Demo2 { @Resource(name="user")//将名为user的对象注入到u变量中 private User u; @Test public void fun1(){ System.out.println(u); } }
spring实现的aop的原理: UserService接口: public interface UserService { void save(); void delete(); void update(); void find(); } UserServiceImple实现类: public class UserServiceImpl implements UserService{ public void save(){ System.out.println("保存用户"); } public void delete(){ System.out.println("删除用户"); } public void find(){ System.out.println("查找用户"); } public void update(){ System.out.println("更新用户"); } }
1.动态代理:(优先) 被代理的对象必须要实现接口,才能产生代理对象,如果没有接口将不能用动态代理技术 UserServiceProxyFactory代理工厂: public class UserServiceProxyFactory implements InvocationHandler{ public UserServiceProxyFactory(UserService us){ this.us=us; } private UserService us; public UserService getUserServiceProxy(){ //生成动态代理 UserService usProxy=(UserService)Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(), UserServiceImpl.class.getInterfaces(), this); return usProxy; } @Override public Object invoke(Object arg0, Method method, Object[] arg2) throws Throwable { System.out.println("打开事务");; Object invoke=method.invoke(us,arg2); System.out.println("提交事务"); return null; } }
测试类: @Test public void fun1(){ UserService us=new UserServiceImpl(); UserServiceProxyFactory factory=new UserServiceProxyFactory(us); UserService usPorxy=factory.getUserServiceProxy(); usPorxy.save(); }
2.cglib代理: 第三方代理技术,cglib代理,可以对任何类型生成代理,代理的原理是对目标对象进行继承代理,如果目标对象被final修饰,那么该类无法被cglib代理 UserServiceProxyFactory2工厂类: public class UserServiceProxyFactory2 implements MethodInterceptor{ public UserService getUserServiceProxy(){ Enhancer en=new Enhancer();//帮我们生成代理对象 en.setSuperclass(UserServiceImpl.class);//设置对谁进行代理 en.setCallback(this);//代理要做什么 UserService us=(UserService)en.create();//创建代理对象 return us; } @Override public Object intercept(Object proxyobj, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable { //打开事务 System.out.println("打开事务"); //调用原有方法 Object returnValue=methodProxy.invokeSuper(proxyobj, arg); //提交事务 System.out.println("提交事务"); return returnValue; } }
测试方法: @Test public void fun2(){ UserServiceProxyFactory2 factory=new UserServiceProxyFactory2(); UserService usPorxy=factory.getUserServiceProxy(); usPorxy.save(); //代理对象继承了被代理对象 System.out.println(usPorxy instanceof UserServiceImpl);//判断代理对象是否属于被代理对象类型 }
spring的aop: 通知类:MyAdvice: public class MyAdvice { //前置通知->目标方法之前调用 //后置通知(如果出现异常不会调用)->在目标方法运行之后调用 //环绕通知->在目标方法之前和之后都调用 //异常拦截通知->如果出现异常就会调用 //后置通知(无论出现异常都会调用) public void before(){ System.out.println("这是前置通知"); } public void afterRunning(){ 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("这是后置通知"); } }
配置文件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_aop.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.*(..) --> <aop:pointcut expression="execution(* cn.itcast.service.*ServiceImpl.*(..))" id="pc"/> <aop:aspect ref="myAdvice" > <!-- 指定名为before方法作为前置通知 --> <aop:before method="before" pointcut-ref="pc" /> <!-- 后置 --> <aop:after-returning method="afterRunning" 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>
测试类: @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:/cn/itcast/d_aop/applicationContext.xml") public class Demo { @Resource(name="userService") private UserService us; @Test public void fun1(){ us.save(); } }
spring的aop注解配置: 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.e_annotation.MyAdvice" ></bean> <!-- 3.开启使用注解完成植入 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
@Aspect//表示该类是一个通知类 public class MyAdvice { //前置通知->目标方法之前调用 //后置通知(如果出现异常不会调用)->在目标方法运行之后调用 //环绕通知->在目标方法之前和之后都调用 //异常拦截通知->如果出现异常就会调用 //后置通知(无论出现异常都会调用) //指定该方法是前置通知并制定切入点 @Pointcut("execution(* cn.itcast.service.*ServiceImpl.*(..))") public void pc(){ } @Before("MyAdvice.pc()") public void before(){ System.out.println("这是前置通知"); } @AfterReturning("execution(* cn.itcast.service.*ServiceImpl.*(..))") public void afterRunning(){ System.out.println("这是后置通知,如果出现异常不会调用"); } @Around("execution(* cn.itcast.service.*ServiceImpl.*(..))") public Object around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("在环绕通知之前的部分"); Object proceed=pjp.proceed();//调用目标方法 System.out.println("在环绕通知之后的部分"); return proceed; } @AfterThrowing("execution(* cn.itcast.service.*ServiceImpl.*(..))") public void afterException(){ System.out.println("出事啦出现异常了"); } @After("execution(* cn.itcast.service.*ServiceImpl.*(..))") public void after(){ System.out.println("这是后置通知"); } }
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:cn/itcast/e_annotation/applicationContext.xml") public class Demo { @Resource(name="userService") private UserService us; @Test public void fun1(){ us.save(); } }