Spring框架基础2

测试Spring的AOP思想和注解的使用

导包(在前面的基础上添加)

SpringAOP名词解释

  1. AOP编程思想:横向重复代码,纵向抽取;就是说多个地方重复的代码可以抽取出来公用(过滤器等可以体现)
    动态代理:动态代理可以体现AOP思想;对目标方法进行增强
    SpringAOP开发:封装了动态代理代码(包括cglib代理),可以对任何类进行代理增强
    Joinpoint(连接点):目标对象中,所有可以增强的方法
    Pointcut(切入点):目标对象,已经增强的方法
    Advice(通知/增强):增强的代码
    Target(目标对象):被代理对象
    Weaving(织入):将通知应用到切入点的过程
    Proxy(代理):将通知织入到目标对象之后,形成代理对象
    aspect(切面):切入点+通知

创建配置文件(如图由上至下)

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- 使用某个标签之前要导入相应的约束 -->
  3. <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns="http://www.springframework.org/schema/beans"
  5. xmlns:context="http://www.springframework.org/schema/context"
  6. xmlns:aop="http://www.springframework.org/schema/aop"
  7. xsi:schemaLocation="http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
  9. http://www.springframework.org/schema/context
  10. http://www.springframework.org/schema/context/spring-context-4.2.xsd
  11. http://www.springframework.org/schema/aop
  12. http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">
  13.  
  14. <!-- 配置目标对象 -->
  15. <bean name="userService" class="com.service.UserServiceImpl"></bean>
  16. <!-- 配置通知对象 -->
  17. <bean name="myAdvice" class="com.anno.MyAdvice"></bean>
  18. <!-- 将通知织入目标对象,利用注解实现 -->
  19. <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  20. </beans>
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- 使用某个标签之前要导入相应的约束 -->
  3. <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns="http://www.springframework.org/schema/beans"
  5. xmlns:context="http://www.springframework.org/schema/context"
  6. xmlns:aop="http://www.springframework.org/schema/aop"
  7. xsi:schemaLocation="http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
  9. http://www.springframework.org/schema/context
  10. http://www.springframework.org/schema/context/spring-context-4.2.xsd
  11. http://www.springframework.org/schema/aop
  12. http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">
  13.  
  14. <!-- 配置目标对象 -->
  15. <bean name="userServiceTarget" class="com.service.UserServiceImpl"></bean>
  16. <!-- 配置通知对象 -->
  17. <bean name="myAdvice" class="com.aspect.MyAdvice"></bean>
  18. <!-- 将通知织入目标对象 -->
  19. <aop:config>
  20. <!-- 配置切入点,即需要加强功能的方法
  21. public void com.service.UserServiceImpl.save()
  22. void com.service.UserServiceImpl.save()
  23. * com.service.UserServiceImpl.save()
  24. * com.service.UserServiceImpl.*
  25. * com.service.UserServiceImpl.*(..)
  26. * com.service.*ServiceImpl.*(..)-->
  27. <aop:pointcut id="pc" expression="execution(* com.service.*ServiceImpl.*(..))"/>
  28. <aop:aspect ref="myAdvice">
  29. <!-- 将myAdvice的before切入到UserServiceImpl.save() -->
  30. <aop:before method="before" pointcut-ref="pc"/>
  31. <aop:after-returning method="afterReturning" pointcut-ref="pc"/>
  32. <aop:around method="around" pointcut-ref="pc"/>
  33. <aop:after-throwing method="afterException" pointcut-ref="pc"/>
  34. <aop:after method="after" pointcut-ref="pc"/>
  35. </aop:aspect>
  36. </aop:config>
  37. </beans>
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns="http://www.springframework.org/schema/beans"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
  7. http://www.springframework.org/schema/context
  8. http://www.springframework.org/schema/context/spring-context-4.2.xsd ">
  9.  
  10. <!-- 扫描相应包下的类的所有注解 -->
  11. <!-- 会扫描该包下的所有子孙类 -->
  12. <context:component-scan base-package="com.bean"/>
  13.  
  14. <bean name="car2" class="com.bean.Car">
  15. <property name="name" value="玛莎拉蒂"/>
  16. <property name="color" value="red"/>
  17. </bean>
  18.  
  19. </beans>

相应的实体类与接口

  1. package com.bean;
  2.  
  3. import org.springframework.beans.factory.annotation.Value;
  4. import org.springframework.stereotype.Component;
  5.  
  6. /**
  7. * @author: XDZY
  8. * @date: 2018/9/5 23:38
  9. * @description: 车辆实体类
  10. */
  11. @Component("car")
  12. public class Car {
  13. @Value("兰博基尼")
  14. private String name;
  15. @Value("red")
  16. private String color;
  17.  
  18. public String getName() {
  19. return name;
  20. }
  21.  
  22. public void setName(String name) {
  23. this.name = name;
  24. }
  25.  
  26. public String getColor() {
  27. return color;
  28. }
  29.  
  30. public void setColor(String color) {
  31. this.color = color;
  32. }
  33.  
  34. @Override
  35. public String toString() {
  36. return "Car{" +
  37. "name='" + name + '\'' +
  38. ", color='" + color + '\'' +
  39. '}';
  40. }
  41. }
  1. package com.bean;
  2.  
  3. import org.springframework.beans.factory.annotation.Value;
  4. import org.springframework.stereotype.Component;
  5.  
  6. import javax.annotation.PostConstruct;
  7. import javax.annotation.PreDestroy;
  8. import javax.annotation.Resource;
  9.  
  10. /**
  11. * @author: XDZY
  12. * @date: 2018/9/5 19:31
  13. * @description: 用户实体类
  14. * 通过注解获取对象
  15. * "@Component("user")==<bean name="user" class="com.bean.User"/>"
  16. */
  17. @Component("user")
  18. //@Service("user")指定为service层
  19. //@Controller("user")指定为web层
  20. //@Repository("user")指定为dao层
  21. //单例还是多例
  22. //@Scope(scopeName = "singleton")
  23. public class User {
  24. //通过反射设置值,破坏了封装性
  25. @Value("xdzy")
  26. private String name;
  27. @Value("15")
  28. private int age;
  29.  
  30. //自动配置car属性;但是有多个对象时,不知道获取哪个
  31. //@Autowired
  32. //指定哪个对象
  33. //@Qualifier("car2")
  34. //手动注解使用哪个car
  35. @Resource(name = "car2")
  36. private Car car;
  37.  
  38. //创建对象前调用
  39. @PostConstruct
  40. public void init() {
  41. System.out.println("初始化方法");
  42. }
  43.  
  44. //对象销毁前调用
  45. @PreDestroy
  46. public void destroy() {
  47. System.out.println("销毁方法");
  48. }
  49.  
  50. public Car getCar() {
  51. return car;
  52. }
  53.  
  54. public void setCar(Car car) {
  55. this.car = car;
  56. }
  57.  
  58. public String getName() {
  59. return name;
  60. }
  61.  
  62. //通过set设置值,推荐使用
  63. @Value("xdzy")
  64. public void setName(String name) {
  65. this.name = name;
  66. }
  67.  
  68. public int getAge() {
  69. return age;
  70. }
  71.  
  72. public void setAge(int age) {
  73. this.age = age;
  74. }
  75.  
  76. @Override
  77. public String toString() {
  78. return "User{" +
  79. "name='" + name + '\'' +
  80. ", age=" + age +
  81. ", car=" + car +
  82. '}';
  83. }
  84. }
  1. package com.service;
  2.  
  3. /**
  4. * @author: XDZY
  5. * @date: 2018/9/6 20:21
  6. * @description:
  7. */
  8. public interface UserService {
  9. void save();
  10.  
  11. void del();
  12.  
  13. void update();
  14.  
  15. void find();
  16. }
  1. package com.service;
  2.  
  3. /**
  4. * @author: XDZY
  5. * @date: 2018/9/6 20:22
  6. * @description:
  7. */
  8. public class UserServiceImpl implements UserService {
  9. @Override
  10. public void save() {
  11. System.out.println("增加用户");
  12. }
  13.  
  14. @Override
  15. public void del() {
  16. System.out.println("删除用户");
  17. }
  18.  
  19. @Override
  20. public void update() {
  21. System.out.println("修改用户");
  22. }
  23.  
  24. @Override
  25. public void find() {
  26. System.out.println("查询用户");
  27. }
  28. }

JDK动态代理

  1. package com.service;
  2.  
  3. import java.lang.reflect.InvocationHandler;
  4. import java.lang.reflect.Method;
  5. import java.lang.reflect.Proxy;
  6.  
  7. /**
  8. * @author: XDZY
  9. * @date: 2018/9/6 20:25
  10. * @description: JDK动态代理
  11. * 被代理对象必须要实现接口,才能产生代理对象,如果没有接口将不能使用动态代理技术
  12. * 动态代理可对方法进行增强,如增加事务的打开与提交
  13. * 个人理解:它是对service实现类里所有的方法进行了增强;
  14. * 在不破坏原有结构的情况下,生成动态代理对象,对原有方法进行增强
  15. */
  16. public class UserServiceProxyFactory implements InvocationHandler {
  17. private UserService us;
  18.  
  19. public UserServiceProxyFactory(UserService us) {
  20. this.us = us;
  21. }
  22.  
  23. public UserService getUserServiceProxy() {
  24. //生成动态代理
  25. UserService userProxy = (UserService) Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(),
  26. UserServiceImpl.class.getInterfaces(),
  27. this);
  28. //返回一个动态代理对象
  29. return userProxy;
  30. }
  31.  
  32. @Override
  33. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  34. System.out.println("打开事务");
  35. Object invoke = method.invoke(us, args);
  36. System.out.println("提交事务");
  37. return invoke;
  38. }
  39. }

Cglib代理

  1. package com.service;
  2.  
  3. import org.springframework.cglib.proxy.Enhancer;
  4. import org.springframework.cglib.proxy.MethodInterceptor;
  5. import org.springframework.cglib.proxy.MethodProxy;
  6.  
  7. import java.lang.reflect.Method;
  8.  
  9. /**
  10. * @author: XDZY
  11. * @date: 2018/9/6 20:25
  12. * @description: Cglib动态代理
  13. * 可以对任何类生成代理,对目标对象进行继承代理
  14. */
  15. public class UserServiceProxyFactory2 implements MethodInterceptor {
  16. public UserService getUserServiceProxy() {
  17. //生成代理对象
  18. Enhancer en = new Enhancer();
  19. //对谁进行代理
  20. en.setSuperclass(UserServiceImpl.class);
  21. //代理要做什么
  22. en.setCallback(this);
  23. //创建代理对象
  24. UserService us = (UserService) en.create();
  25. return us;
  26. }
  27.  
  28. @Override
  29. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  30. //打开事务
  31. System.out.println("打开事务");
  32. //调用原有方法
  33. Object returnValue = methodProxy.invokeSuper(o, objects);
  34. //提交事务
  35. System.out.println("提交事务");
  36. return returnValue;
  37. }
  38. }

通知类

  1. package com.anno;
  2.  
  3. import org.aspectj.lang.ProceedingJoinPoint;
  4. import org.aspectj.lang.annotation.*;
  5.  
  6. /**
  7. * @author: XDZY
  8. * @date: 2018/9/7 08:23
  9. * @description: 利用注解实现通知
  10. * "@Aspect:表示该类是一个通知类
  11. */
  12. @Aspect
  13. public class MyAdvice {
  14. //方便管理切入点
  15. @Pointcut("execution(* com.service.*ServiceImpl.*(..))")
  16. public void pc() {
  17. }
  18.  
  19. //配置通知,并指定织入到哪去
  20. //前置通知:目标方法运行之前
  21. @Before("MyAdvice.pc()")
  22. public void before() {
  23. System.out.println("前置通知");
  24. }
  25.  
  26. //后置通知(如果出现异常不会调用):之后
  27. @AfterReturning("execution(* com.service.*ServiceImpl.*(..))")
  28. public void afterReturning() {
  29. System.out.println("后置通知(如果出现异常不会调用)");
  30. }
  31.  
  32. //环绕通知:之前之后
  33. @Around("execution(* com.service.*ServiceImpl.*(..))")
  34. public Object around(ProceedingJoinPoint pjp) throws Throwable {
  35. System.out.println("环绕通知之前部分");
  36. //调用目标方法
  37. Object proceed = pjp.proceed();
  38. System.out.println("环绕通知之后部分");
  39. return proceed;
  40. }
  41.  
  42. //异常拦截通知:出现异常调用
  43. @AfterThrowing("execution(* com.service.*ServiceImpl.*(..))")
  44. public void afterException() {
  45. System.out.println("出现异常调用");
  46. }
  47.  
  48. //后置通知(无论是否出现异常都会调用):之后
  49. @After("execution(* com.service.*ServiceImpl.*(..))")
  50. public void after() {
  51. System.out.println("后置通知(无论是否出现异常都会调用)");
  52. }
  53. }
  1. package com.aspect;
  2.  
  3. import org.aspectj.lang.ProceedingJoinPoint;
  4.  
  5. /**
  6. * @author: XDZY
  7. * @date: 2018/9/7 08:23
  8. * @description: 通知
  9. * 前置通知:目标方法运行之前
  10. * 后置通知(如果出现异常不会调用):之后
  11. * 环绕通知:之前之后
  12. * 异常拦截通知:出现异常调用
  13. * 后置通知(无论是否出现异常都会调用):之后
  14. */
  15. public class MyAdvice {
  16. //前置通知:目标方法运行之前
  17. public void before() {
  18. System.out.println("前置通知");
  19. }
  20.  
  21. //后置通知(如果出现异常不会调用):之后
  22. public void afterReturning() {
  23. System.out.println("后置通知(如果出现异常不会调用)");
  24. }
  25.  
  26. //环绕通知:之前之后
  27. public Object around(ProceedingJoinPoint pjp) throws Throwable {
  28. System.out.println("环绕通知之前部分");
  29. //调用目标方法
  30. Object proceed = pjp.proceed();
  31. System.out.println("环绕通知之后部分");
  32. return proceed;
  33. }
  34.  
  35. //异常拦截通知:出现异常调用
  36. public void afterException() {
  37. System.out.println("出现异常调用");
  38. }
  39.  
  40. //后置通知(无论是否出现异常都会调用):之后
  41. public void after() {
  42. System.out.println("后置通知(无论是否出现异常都会调用)");
  43. }
  44. }

测试类

  1. package com.test;
  2.  
  3. import com.service.UserService;
  4. import com.service.UserServiceImpl;
  5. import com.service.UserServiceProxyFactory;
  6. import com.service.UserServiceProxyFactory2;
  7. import org.junit.Test;
  8. import org.springframework.context.ApplicationContext;
  9. import org.springframework.context.support.ClassPathXmlApplicationContext;
  10.  
  11. /**
  12. * @author: XDZY
  13. * @date: 2018/9/6 09:32
  14. * @description: 测试注解获取对象
  15. * "@RunWith:可以帮助我们创建容器,这样xml地址改动,测试方法不用全部修改
  16. * "@ContextConfiguration:指定容器位置
  17. * 注意junit版本问题
  18. */
  19. //@RunWith(SpringJUnit4ClassRunner.class)
  20. //@ContextConfiguration("classpath:resources/applicationContext.xml")
  21. public class Demo1 {
  22. /*@Resource(name = "user")
  23. private User user;
  24.  
  25. @Test
  26. public void test(){
  27. System.out.println(user);
  28. }*/
  29.  
  30. //JDK动态代理
  31. @Test
  32. public void test1() {
  33. UserService us = new UserServiceImpl();
  34. UserServiceProxyFactory factory = new UserServiceProxyFactory(us);
  35. UserService userProxy = factory.getUserServiceProxy();
  36. userProxy.save();
  37.  
  38. //代理对象和被代理对象实现了相同的接口(false)
  39. System.out.println(userProxy instanceof UserServiceImpl);
  40. }
  41.  
  42. //Cglib动态代理
  43. @Test
  44. public void test2() {
  45. UserServiceProxyFactory2 factory = new UserServiceProxyFactory2();
  46. UserService userProxy = factory.getUserServiceProxy();
  47. userProxy.save();
  48.  
  49. //代理对象继承了被代理对象(true)
  50. System.out.println(userProxy instanceof UserServiceImpl);
  51. }
  52.  
  53. //通知织入
  54. @Test
  55. public void test() {
  56. //创建容器对象
  57. ApplicationContext ac = new ClassPathXmlApplicationContext("com/aop/applicationContext.xml");
  58. //获取user对象
  59. UserService userService = (UserService) ac.getBean("userServiceTarget");
  60. userService.save();
  61. }
  62.  
  63. //注解通知织入
  64. @Test
  65. public void test4() {
  66. //创建容器对象
  67. ApplicationContext ac = new ClassPathXmlApplicationContext("com/anno/applicationContext.xml");
  68. //获取user对象
  69. UserService userService = (UserService) ac.getBean("userService");
  70. userService.save();
  71. }
  72. }

Spring框架基础2的更多相关文章

  1. Spring学习指南-第二章-Spring框架基础(完)

    第二章 Spring框架基础 面向接口编程的设计方法 ​ 在上一章中,我们看到了一个依赖于其他类的POJO类包含了对其依赖项的具体类的引用.例如,FixedDepositController 类包含 ...

  2. 4-1 Spring框架基础知识

    Spring框架基础知识 1.Spring 框架作用 主要解决了创建对象和管理对象的问题. 自动装配机制 2.Spring 框架 (Spring容器,JavaBean容器,Bean容器,Spring容 ...

  3. Spring框架基础知识

    本人博客文章网址:https://www.peretang.com/basic-knowledge-of-spring-framework/ Spring框架简介 Spring , 一个开源的框架 , ...

  4. Spring框架基础

    1         Spring框架 1.1           Spring的基本概念 是一个轻量级的框架,提供基础的开发包,包括消息.web通讯.数据库.大数据.授权.手机应用.session管理 ...

  5. Spring 框架基础(04):AOP切面编程概念,几种实现方式演示

    本文源码:GitHub·点这里 || GitEE·点这里 一.AOP基础简介 1.切面编程简介 AOP全称:Aspect Oriented Programming,面向切面编程.通过预编译方式和运行期 ...

  6. Spring框架基础解析

    Spring是一个轻量级的.非侵入式的容器框架:对Bean对象的生命周期进行管理. Spring框架的核心:IOC(控制反转).DI(依赖注入).AOP(面向切面编程). (1) IOC:控制反转. ...

  7. Spring 框架基础(06):Mvc架构模式简介,执行流程详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.SpringMvc框架简介 1.Mvc设计理念 MVC是一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集 ...

  8. Spring 框架基础(03):核心思想 IOC 说明,案例演示

    本文源码:GitHub·点这里 || GitEE·点这里 一.IOC控制反转 1.IOC容器思想 Java系统中对象耦合关系十分复杂,系统的各模块之间依赖,微服务模块之间的相互调用请求,都是这个道理. ...

  9. Spring 框架基础(02):Bean的生命周期,作用域,装配总结

    本文源码:GitHub·点这里 || GitEE·点这里 一.装配方式 Bean的概念:Spring框架管理的应用程序中,由Spring容器负责创建,装配,设置属性,进而管理整个生命周期的对象,称为B ...

随机推荐

  1. 配置python环境使用tushare股票数据

    最近在做一个项目,主要是基于股票市场来验证一些model,看看能否做量化交易.那么如何获取数据呢?因为客户这边前期是不想花钱买数据的,只能自己想办法了,从sina和yahoo财经频道爬到一些数据,但是 ...

  2. phpwind本地安装 inernal server error错误

    wampserver2.2环境,本地安装phpwind9.0时出错: Internal Server Error The server encountered an internal error or ...

  3. mathjax符号

    mathjax公式 \(\delta\): \delta \(\Delta\): \Delta \(\int\): \int \(\iint\): \iint \(\approx\): \approx ...

  4. 如何绘制ER图

    先画出多个实体(用长方形表示),然后是联系类型(菱形),和属性(椭圆).

  5. eclipse 构建从 SVN 上下载的可识别的 maven 项目

    从 SVN 上下载的 maven 项目中含有父项目,属于 maven 的嵌套,每个子项目和父项目虽有 pom.xml 文件,在结构上也是 maven 然而并不是 eclipse 识别的 maven 项 ...

  6. Vue编译时写在style中的路径问题

    写在vue文件里面的style样式,在添加例如背景图片的时候,如果用的是相对路径,那么build出来的css文件的路径将会出错,导致找不到图片. 通过查找资料,在https://segmentfaul ...

  7. fd_set实现原理

    fd_set是一个结构 /* The fd_set member is required to be an array of longs. */ typedef long int __fd_mask; ...

  8. Android Studio快捷键【Android学习入门】

    Studio快捷键[Android学习入门]" title="Android Studio快捷键[Android学习入门]"> 提示 Ctrl+P方法参数提示 Ct ...

  9. Android触摸事件MotionEvent详解

    触摸事件MotionEvent在用户交互中,占着非常重要的地位.首先,来看看MotionEvent中封装的一些常用的事件常量,它定义了触摸事件的不同类型. 1.单点触摸按下动作 public stat ...

  10. Qt开发北斗定位系统融合百度地图API及Qt程序打包发布

    Qt开发北斗定位系统融合百度地图API及Qt程序打包发布 1.上位机介绍 最近有个接了一个小型项目,内容很简单,就是解析北斗GPS的串口数据然后输出经纬度,但接过来觉得太简单,就发挥了主观能动性,增加 ...