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 ...
随机推荐
- php 关于时间的函数
//返回1970年1月1日零点以来的秒数. //定义为从格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数. time(); ...
- HDU 4009——Transfer water——————【最小树形图、不定根】
Transfer water Time Limit:3000MS Memory Limit:65768KB 64bit IO Format:%I64d & %I64u Subm ...
- linux下常用命令备忘
转自:Linux 命令集锦 linux下查看监听端口对应的进程 # lsof -i:9000 # lsof -Pnl +M -i4 如果退格键变成了:"^h". 终端连接unix删 ...
- java 多线程操作(锁)
1.对象的加锁及其操作 程序中单独的并发线程对同一对象进行操作的代码段,成为临界区.java语言中的临界区可以是一个语句块 或者方法,使用关键字synchronized进行标识. 对象锁:java平台 ...
- Java中的阻塞队列-ArrayBlockingQueue(一)
最近在看一些java基础的东西,看到了队列这章,打算对复习的一些知识点做一个笔记,也算是对自己思路的一个整理,本章先聊聊java中的阻塞队列 参考文章: http://ifeve.com/java-b ...
- 什么是MongoDb
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型.Mo ...
- The seventeenth day
A good book is a good friend 好书如挚友
- Python:Tkinter的GUI设计——物体实时移动
参考: 1.Tkinter之Canvas篇 2.python GUI实践:做一个满图乱跑的小球 3.[Tkinter 教程08] Canvas 图形绘制 4.tkinter模块常用参数(python3 ...
- JS的定时到底有多不准
博客逐步迁移到,独立博客,原文地址,http://www.woniubi.cn/js_hide_tab_setinterval/ 我们一直都在说,JS的定时非常的不准确,但是很少有人去验证他,今天我就 ...
- [转]WinForm下Splash(启动画面)制作
本文转自:http://www.smartgz.com/blog/Article/1088.asp 原文如下: 本代码可以依据主程序加载进度来显示Splash. static class Progra ...