Spring框架基础2
Spring框架基础2
测试Spring的AOP思想和注解的使用
导包(在前面的基础上添加)
SpringAOP名词解释
- AOP编程思想:横向重复代码,纵向抽取;就是说多个地方重复的代码可以抽取出来公用(过滤器等可以体现)
动态代理:动态代理可以体现AOP思想;对目标方法进行增强
SpringAOP开发:封装了动态代理代码(包括cglib代理),可以对任何类进行代理增强
Joinpoint(连接点):目标对象中,所有可以增强的方法
Pointcut(切入点):目标对象,已经增强的方法
Advice(通知/增强):增强的代码
Target(目标对象):被代理对象
Weaving(织入):将通知应用到切入点的过程
Proxy(代理):将通知织入到目标对象之后,形成代理对象
aspect(切面):切入点+通知
创建配置文件(如图由上至下)
- <?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 ">
- <!-- 配置目标对象 -->
- <bean name="userService" class="com.service.UserServiceImpl"></bean>
- <!-- 配置通知对象 -->
- <bean name="myAdvice" class="com.anno.MyAdvice"></bean>
- <!-- 将通知织入目标对象,利用注解实现 -->
- <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
- </beans>
- <?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 ">
- <!-- 配置目标对象 -->
- <bean name="userServiceTarget" class="com.service.UserServiceImpl"></bean>
- <!-- 配置通知对象 -->
- <bean name="myAdvice" class="com.aspect.MyAdvice"></bean>
- <!-- 将通知织入目标对象 -->
- <aop:config>
- <!-- 配置切入点,即需要加强功能的方法
- public void com.service.UserServiceImpl.save()
- void com.service.UserServiceImpl.save()
- * com.service.UserServiceImpl.save()
- * com.service.UserServiceImpl.*
- * com.service.UserServiceImpl.*(..)
- * com.service.*ServiceImpl.*(..)-->
- <aop:pointcut id="pc" expression="execution(* com.service.*ServiceImpl.*(..))"/>
- <aop:aspect ref="myAdvice">
- <!-- 将myAdvice的before切入到UserServiceImpl.save() -->
- <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>
- <?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"
- 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 ">
- <!-- 扫描相应包下的类的所有注解 -->
- <!-- 会扫描该包下的所有子孙类 -->
- <context:component-scan base-package="com.bean"/>
- <bean name="car2" class="com.bean.Car">
- <property name="name" value="玛莎拉蒂"/>
- <property name="color" value="red"/>
- </bean>
- </beans>
相应的实体类与接口
- package com.bean;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.stereotype.Component;
- /**
- * @author: XDZY
- * @date: 2018/9/5 23:38
- * @description: 车辆实体类
- */
- @Component("car")
- public class Car {
- @Value("兰博基尼")
- private String name;
- @Value("red")
- private String color;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getColor() {
- return color;
- }
- public void setColor(String color) {
- this.color = color;
- }
- @Override
- public String toString() {
- return "Car{" +
- "name='" + name + '\'' +
- ", color='" + color + '\'' +
- '}';
- }
- }
- package com.bean;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.stereotype.Component;
- import javax.annotation.PostConstruct;
- import javax.annotation.PreDestroy;
- import javax.annotation.Resource;
- /**
- * @author: XDZY
- * @date: 2018/9/5 19:31
- * @description: 用户实体类
- * 通过注解获取对象
- * "@Component("user")==<bean name="user" class="com.bean.User"/>"
- */
- @Component("user")
- //@Service("user")指定为service层
- //@Controller("user")指定为web层
- //@Repository("user")指定为dao层
- //单例还是多例
- //@Scope(scopeName = "singleton")
- public class User {
- //通过反射设置值,破坏了封装性
- @Value("xdzy")
- private String name;
- @Value("15")
- private int age;
- //自动配置car属性;但是有多个对象时,不知道获取哪个
- //@Autowired
- //指定哪个对象
- //@Qualifier("car2")
- //手动注解使用哪个car
- @Resource(name = "car2")
- private Car car;
- //创建对象前调用
- @PostConstruct
- public void init() {
- System.out.println("初始化方法");
- }
- //对象销毁前调用
- @PreDestroy
- public void destroy() {
- System.out.println("销毁方法");
- }
- public Car getCar() {
- return car;
- }
- public void setCar(Car car) {
- this.car = car;
- }
- public String getName() {
- return name;
- }
- //通过set设置值,推荐使用
- @Value("xdzy")
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- @Override
- public String toString() {
- return "User{" +
- "name='" + name + '\'' +
- ", age=" + age +
- ", car=" + car +
- '}';
- }
- }
- package com.service;
- /**
- * @author: XDZY
- * @date: 2018/9/6 20:21
- * @description:
- */
- public interface UserService {
- void save();
- void del();
- void update();
- void find();
- }
- package com.service;
- /**
- * @author: XDZY
- * @date: 2018/9/6 20:22
- * @description:
- */
- public class UserServiceImpl implements UserService {
- @Override
- public void save() {
- System.out.println("增加用户");
- }
- @Override
- public void del() {
- System.out.println("删除用户");
- }
- @Override
- public void update() {
- System.out.println("修改用户");
- }
- @Override
- public void find() {
- System.out.println("查询用户");
- }
- }
JDK动态代理
- package com.service;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- /**
- * @author: XDZY
- * @date: 2018/9/6 20:25
- * @description: JDK动态代理
- * 被代理对象必须要实现接口,才能产生代理对象,如果没有接口将不能使用动态代理技术
- * 动态代理可对方法进行增强,如增加事务的打开与提交
- * 个人理解:它是对service实现类里所有的方法进行了增强;
- * 在不破坏原有结构的情况下,生成动态代理对象,对原有方法进行增强
- */
- public class UserServiceProxyFactory implements InvocationHandler {
- private UserService us;
- public UserServiceProxyFactory(UserService us) {
- this.us = us;
- }
- public UserService getUserServiceProxy() {
- //生成动态代理
- UserService userProxy = (UserService) Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(),
- UserServiceImpl.class.getInterfaces(),
- this);
- //返回一个动态代理对象
- return userProxy;
- }
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- System.out.println("打开事务");
- Object invoke = method.invoke(us, args);
- System.out.println("提交事务");
- return invoke;
- }
- }
Cglib代理
- package com.service;
- import org.springframework.cglib.proxy.Enhancer;
- import org.springframework.cglib.proxy.MethodInterceptor;
- import org.springframework.cglib.proxy.MethodProxy;
- import java.lang.reflect.Method;
- /**
- * @author: XDZY
- * @date: 2018/9/6 20:25
- * @description: Cglib动态代理
- * 可以对任何类生成代理,对目标对象进行继承代理
- */
- 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 o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
- //打开事务
- System.out.println("打开事务");
- //调用原有方法
- Object returnValue = methodProxy.invokeSuper(o, objects);
- //提交事务
- System.out.println("提交事务");
- return returnValue;
- }
- }
通知类
- package com.anno;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.*;
- /**
- * @author: XDZY
- * @date: 2018/9/7 08:23
- * @description: 利用注解实现通知
- * "@Aspect:表示该类是一个通知类
- */
- @Aspect
- public class MyAdvice {
- //方便管理切入点
- @Pointcut("execution(* com.service.*ServiceImpl.*(..))")
- public void pc() {
- }
- //配置通知,并指定织入到哪去
- //前置通知:目标方法运行之前
- @Before("MyAdvice.pc()")
- public void before() {
- System.out.println("前置通知");
- }
- //后置通知(如果出现异常不会调用):之后
- @AfterReturning("execution(* com.service.*ServiceImpl.*(..))")
- public void afterReturning() {
- System.out.println("后置通知(如果出现异常不会调用)");
- }
- //环绕通知:之前之后
- @Around("execution(* com.service.*ServiceImpl.*(..))")
- public Object around(ProceedingJoinPoint pjp) throws Throwable {
- System.out.println("环绕通知之前部分");
- //调用目标方法
- Object proceed = pjp.proceed();
- System.out.println("环绕通知之后部分");
- return proceed;
- }
- //异常拦截通知:出现异常调用
- @AfterThrowing("execution(* com.service.*ServiceImpl.*(..))")
- public void afterException() {
- System.out.println("出现异常调用");
- }
- //后置通知(无论是否出现异常都会调用):之后
- @After("execution(* com.service.*ServiceImpl.*(..))")
- public void after() {
- System.out.println("后置通知(无论是否出现异常都会调用)");
- }
- }
- package com.aspect;
- import org.aspectj.lang.ProceedingJoinPoint;
- /**
- * @author: XDZY
- * @date: 2018/9/7 08:23
- * @description: 通知
- * 前置通知:目标方法运行之前
- * 后置通知(如果出现异常不会调用):之后
- * 环绕通知:之前之后
- * 异常拦截通知:出现异常调用
- * 后置通知(无论是否出现异常都会调用):之后
- */
- 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("后置通知(无论是否出现异常都会调用)");
- }
- }
测试类
- package com.test;
- import com.service.UserService;
- import com.service.UserServiceImpl;
- import com.service.UserServiceProxyFactory;
- import com.service.UserServiceProxyFactory2;
- import org.junit.Test;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- /**
- * @author: XDZY
- * @date: 2018/9/6 09:32
- * @description: 测试注解获取对象
- * "@RunWith:可以帮助我们创建容器,这样xml地址改动,测试方法不用全部修改
- * "@ContextConfiguration:指定容器位置
- * 注意junit版本问题
- */
- //@RunWith(SpringJUnit4ClassRunner.class)
- //@ContextConfiguration("classpath:resources/applicationContext.xml")
- public class Demo1 {
- /*@Resource(name = "user")
- private User user;
- @Test
- public void test(){
- System.out.println(user);
- }*/
- //JDK动态代理
- @Test
- public void test1() {
- UserService us = new UserServiceImpl();
- UserServiceProxyFactory factory = new UserServiceProxyFactory(us);
- UserService userProxy = factory.getUserServiceProxy();
- userProxy.save();
- //代理对象和被代理对象实现了相同的接口(false)
- System.out.println(userProxy instanceof UserServiceImpl);
- }
- //Cglib动态代理
- @Test
- public void test2() {
- UserServiceProxyFactory2 factory = new UserServiceProxyFactory2();
- UserService userProxy = factory.getUserServiceProxy();
- userProxy.save();
- //代理对象继承了被代理对象(true)
- System.out.println(userProxy instanceof UserServiceImpl);
- }
- //通知织入
- @Test
- public void test() {
- //创建容器对象
- ApplicationContext ac = new ClassPathXmlApplicationContext("com/aop/applicationContext.xml");
- //获取user对象
- UserService userService = (UserService) ac.getBean("userServiceTarget");
- userService.save();
- }
- //注解通知织入
- @Test
- public void test4() {
- //创建容器对象
- ApplicationContext ac = new ClassPathXmlApplicationContext("com/anno/applicationContext.xml");
- //获取user对象
- UserService userService = (UserService) ac.getBean("userService");
- userService.save();
- }
- }
Spring框架基础2的更多相关文章
- Spring学习指南-第二章-Spring框架基础(完)
第二章 Spring框架基础 面向接口编程的设计方法 在上一章中,我们看到了一个依赖于其他类的POJO类包含了对其依赖项的具体类的引用.例如,FixedDepositController 类包含 ...
- 4-1 Spring框架基础知识
Spring框架基础知识 1.Spring 框架作用 主要解决了创建对象和管理对象的问题. 自动装配机制 2.Spring 框架 (Spring容器,JavaBean容器,Bean容器,Spring容 ...
- Spring框架基础知识
本人博客文章网址:https://www.peretang.com/basic-knowledge-of-spring-framework/ Spring框架简介 Spring , 一个开源的框架 , ...
- Spring框架基础
1 Spring框架 1.1 Spring的基本概念 是一个轻量级的框架,提供基础的开发包,包括消息.web通讯.数据库.大数据.授权.手机应用.session管理 ...
- Spring 框架基础(04):AOP切面编程概念,几种实现方式演示
本文源码:GitHub·点这里 || GitEE·点这里 一.AOP基础简介 1.切面编程简介 AOP全称:Aspect Oriented Programming,面向切面编程.通过预编译方式和运行期 ...
- Spring框架基础解析
Spring是一个轻量级的.非侵入式的容器框架:对Bean对象的生命周期进行管理. Spring框架的核心:IOC(控制反转).DI(依赖注入).AOP(面向切面编程). (1) IOC:控制反转. ...
- Spring 框架基础(06):Mvc架构模式简介,执行流程详解
本文源码:GitHub·点这里 || GitEE·点这里 一.SpringMvc框架简介 1.Mvc设计理念 MVC是一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集 ...
- Spring 框架基础(03):核心思想 IOC 说明,案例演示
本文源码:GitHub·点这里 || GitEE·点这里 一.IOC控制反转 1.IOC容器思想 Java系统中对象耦合关系十分复杂,系统的各模块之间依赖,微服务模块之间的相互调用请求,都是这个道理. ...
- Spring 框架基础(02):Bean的生命周期,作用域,装配总结
本文源码:GitHub·点这里 || GitEE·点这里 一.装配方式 Bean的概念:Spring框架管理的应用程序中,由Spring容器负责创建,装配,设置属性,进而管理整个生命周期的对象,称为B ...
随机推荐
- 配置python环境使用tushare股票数据
最近在做一个项目,主要是基于股票市场来验证一些model,看看能否做量化交易.那么如何获取数据呢?因为客户这边前期是不想花钱买数据的,只能自己想办法了,从sina和yahoo财经频道爬到一些数据,但是 ...
- phpwind本地安装 inernal server error错误
wampserver2.2环境,本地安装phpwind9.0时出错: Internal Server Error The server encountered an internal error or ...
- mathjax符号
mathjax公式 \(\delta\): \delta \(\Delta\): \Delta \(\int\): \int \(\iint\): \iint \(\approx\): \approx ...
- 如何绘制ER图
先画出多个实体(用长方形表示),然后是联系类型(菱形),和属性(椭圆).
- eclipse 构建从 SVN 上下载的可识别的 maven 项目
从 SVN 上下载的 maven 项目中含有父项目,属于 maven 的嵌套,每个子项目和父项目虽有 pom.xml 文件,在结构上也是 maven 然而并不是 eclipse 识别的 maven 项 ...
- Vue编译时写在style中的路径问题
写在vue文件里面的style样式,在添加例如背景图片的时候,如果用的是相对路径,那么build出来的css文件的路径将会出错,导致找不到图片. 通过查找资料,在https://segmentfaul ...
- fd_set实现原理
fd_set是一个结构 /* The fd_set member is required to be an array of longs. */ typedef long int __fd_mask; ...
- Android Studio快捷键【Android学习入门】
Studio快捷键[Android学习入门]" title="Android Studio快捷键[Android学习入门]"> 提示 Ctrl+P方法参数提示 Ct ...
- Android触摸事件MotionEvent详解
触摸事件MotionEvent在用户交互中,占着非常重要的地位.首先,来看看MotionEvent中封装的一些常用的事件常量,它定义了触摸事件的不同类型. 1.单点触摸按下动作 public stat ...
- Qt开发北斗定位系统融合百度地图API及Qt程序打包发布
Qt开发北斗定位系统融合百度地图API及Qt程序打包发布 1.上位机介绍 最近有个接了一个小型项目,内容很简单,就是解析北斗GPS的串口数据然后输出经纬度,但接过来觉得太简单,就发挥了主观能动性,增加 ...