spring框架总结(03)重点介绍(Spring框架的第二种核心掌握)
1、Spring的AOP编程
什么是AOP? ----- 在软件行业AOP为Aspect Oriented Programming 也就是面向切面编程,使用AOP编程的好处就是:在不修改源代码的情况下,可以实现代码功能的增强
AOP的实现原理(掌握)
JDK的动态代理(注意JDK的动态代理只能对实现了接口的类产生代理)
/**
* Jdk的动态代理
* @author lilong
*/
public class JdkProxy implements InvocationHandler{
//要代理的对象
private CustomerDao customerDao;
public JdkProxy(CustomerDao customerDao){
this.customerDao = customerDao;
}
/**
* 生成代理对象的方法
* @return
*/
public CustomerDao createProxy(){
CustomerDao proxy = (CustomerDao) Proxy.newProxyInstance(customerDao.getClass().getClassLoader(), customerDao.getClass().getInterfaces(), this);
return proxy;
}
/**
* 增强的方法
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("权限校验...");
return method.invoke(customerDao, args);
}
}
编写测试代码:
@Test
public void test1(){
CustomerDao customerDao = new CustomerDaoImpl();
JdkProxy jdkProxy = new JdkProxy(customerDao);
CustomerDao proxy = jdkProxy.createProxy();
proxy.save();
}
第二种代理方式Cglib方式(了解或者欣赏)
注意的是:Cglib可以对没有实现接口的类产生代理,生成子类来实现功能的增强
public class CglibProxy implements MethodInterceptor{
//要代理的对象
private LinkManDao linkManDao;
public CglibProxy(LinkManDao linkManDao) {
this.linkManDao = linkManDao;
}
public LinkManDao createProxy(){
//创建Cglib核心类
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(linkManDao.getClass());
//设置回调
enhancer.setCallback(this);
//生成代理
LinkManDao proxy = (LinkManDao) enhancer.create();
return proxy;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("日志记录");
Object obj = methodProxy.invokeSuper(proxy, args);
return obj;
}
}
n 编写测试代码
@Test
public void test2(){
LinkManDao linkManDao = new LinkManDao();
CglibProxy cglibProxy = new CglibProxy(linkManDao);
LinkManDao proxy = cglibProxy.createProxy();
proxy.save();
}
2、Spring的AOP开发方式(xml方式)
其中相关术语的介绍
AOP开发所需要的jar介绍
n AOP联盟的jar包:com.springsource.org.aopalliance-1.0.0.jar
n Spring提供的AOP的jar包:spring-aop-4.2.4.RELEASE.jar
n AspectJ的jar包:com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
n Spring整合AspectJ的jar包:spring-aspects-4.2.4.RELEASE.jar
编写接口和实现类
ProductDao接口:
public interface ProductDao {
/**
* 持久层:产品保存
*/
public void save();
}
ProductDaoImpl实现类:
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println("持久层:产品保存...");
}
}
配置相关类到Spring中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="productDao" class="cn.itcast.dao.impl.ProductDaoImpl"></bean>
</beans>
编写切面类
/**
* 自定义切面类
* @author kevin
*/
public class MyAspectXml {
public void checkPrivilege(){
System.out.println("权限校验...");
}
}
配置切面类
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="productDao" class="cn.itcast.dao.impl.ProductDaoImpl"></bean>
<bean id="myAspectXml" class="cn.itcast.aspect.MyAspectXml"></bean>
</beans>
进行AOP配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="productDao" class="cn.itcast.dao.impl.ProductDaoImpl"></bean>
<bean id="myAspectXml" class="cn.itcast.aspect.MyAspectXml"></bean>
<!-- AOP配置 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
</beans>
编写测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestAOP {
@Autowired
private ProductDao productDao;
@Test
public void test1(){
productDao.save();
}
}
总结:对切入点表达式语法进行总结
语法:[修饰符] 返回类型 包名.类名.方法名(形式参数)
常见写法:
n execution(public * *(..)) 所有的public方法
n execution(* set(..)) 所有set开头的方法
n execution(* com.xyz.service.AccountService.*(..)) AccountService类中的所有方法
n execution(* com.xyz.service.*.*(..)) com.xyz.service包下所有的方法
n execution(* com.xyz.service..*.*(..)) com.xyz.service包及其子包下所有的方法
3、Spring中AOP的通知类型
1.1.1. 前置通知:在方法执行之前增强。可以获得切入点信息。
<!-- AOP配置 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<!-- 前置通知 -->
<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
public class MyAspectXml {
public void checkPrivilege(JoinPoint point){
System.out.println("权限校验..." + point);
}
}
1.1.2. 后置通知:在方法执行完之后增强。可以获取返回值信息。
/**
* 自定义切面类
* @author kevin
*/
public class MyAspectXml {
public void checkPrivilege(JoinPoint point){
System.out.println("权限校验..." + point);
}
public void afterReturn(Object result){
System.out.println("后置通知:" + result);
}
}
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println("持久层:产品保存...");
}
public int delete(){
System.out.println("持久层:产品删除...");
return 100;
}
}
<!-- AOP配置 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<!-- 前置通知 -->
<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>
<!-- 后置通知 -->
<aop:after-returning method="afterReturn" pointcut-ref="pointcut2" returning="result"/>
</aop:aspect>
</aop:config>
1.1.3. 环绕通知:在方法执行前后都进行增强。可以阻止方法的执行。
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println("持久层:产品保存...");
}
public int delete(){
System.out.println("持久层:产品删除...");
return 100;
}
@Override
public void update() {
System.out.println("持久层:产品更新");
}
}
public class MyAspectXml {
public void checkPrivilege(JoinPoint point){
System.out.println("权限校验..." + point);
}
public void afterReturn(Object result){
System.out.println("后置通知:" + result);
}
public Object around(ProceedingJoinPoint joinpoint){
System.out.println("环绕前执行");
Object obj = null;
try {
obj = joinpoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("环绕后执行");
return obj;
}
}
<!-- AOP配置 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))" id="pointcut3"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<!-- 前置通知 -->
<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>
<!-- 后置通知 -->
<aop:after-returning method="afterReturn" pointcut-ref="pointcut2" returning="result"/>
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pointcut3"/>
</aop:aspect>
</aop:config>
1.1.4. 异常抛出通知:当发生异常之后增强,可以获取异常信息。
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println("持久层:产品保存...");
}
public int delete(){
System.out.println("持久层:产品删除...");
return 100;
}
@Override
public void update() {
System.out.println("持久层:产品更新");
}
@Override
public void find() {
System.out.println("持久层:查询");
int i = 10/0;
}
}
public class MyAspectXml {
public void checkPrivilege(JoinPoint point){
System.out.println("权限校验..." + point);
}
public void afterReturn(Object result){
System.out.println("后置通知:" + result);
}
public Object around(ProceedingJoinPoint joinpoint){
System.out.println("环绕前执行");
Object obj = null;
try {
obj = joinpoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("环绕后执行");
return obj;
}
public void afterThrowing(Exception ex){
System.out.println("抛出异常通知:" + ex.getMessage());
}
}
<!-- AOP配置 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))" id="pointcut3"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))" id="pointcut4"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<!-- 前置通知 -->
<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>
<!-- 后置通知 -->
<aop:after-returning method="afterReturn" pointcut-ref="pointcut2" returning="result"/>
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pointcut3"/>
<!-- 抛出异常通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
</aop:aspect>
</aop:config>
1.1.5. 最终通知:不管是否有异常,都会执行的
public class MyAspectXml {
public void checkPrivilege(JoinPoint point){
System.out.println("权限校验..." + point);
}
public void afterReturn(Object result){
System.out.println("后置通知:" + result);
}
public Object around(ProceedingJoinPoint joinpoint){
System.out.println("环绕前执行");
Object obj = null;
try {
obj = joinpoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("环绕后执行");
return obj;
}
public void afterThrowing(Exception ex){
System.out.println("抛出异常通知:" + ex.getMessage());
}
public void after(){
System.out.println("最终通知");
}
}
<!-- AOP配置 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))" id="pointcut3"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))" id="pointcut4"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<!-- 前置通知 -->
<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>
<!-- 后置通知 -->
<aop:after-returning method="afterReturn" pointcut-ref="pointcut2" returning="result"/>
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pointcut3"/>
<!-- 抛出异常通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
<!-- 最终通知 -->
<aop:after method="after" pointcut-ref="pointcut4"/>
</aop:aspect>
</aop:config>
注意:最终通知和后置通知的区别:最终通知,不管异常与否,都执行;而后置通知在异常时不执行。
4、Spring的AOP注解
4.1. 创建工程,引入jar包,创建核心配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="cn.itcast"></context:component-scan>
<!-- 开启自动代理注解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
4.2. 创建接口和实现类
public interface ProductDao {
/**
* 持久层:产品保存
*/
public void save();
public int delete();
public void update();
public void find();
}
@Repository("productDao")
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println("持久层:产品保存...");
}
public int delete(){
System.out.println("持久层:产品删除...");
return 100;
}
@Override
public void update() {
System.out.println("持久层:产品更新");
}
@Override
public void find() {
System.out.println("持久层:查询");
}
}
4.3. 编写切面类
@Component("myAspectAnnotation")
@Aspect
public class MyAspect {
@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")
public void checkPrivilege(JoinPoint joinPoint){
System.out.println("权限校验..." + joinPoint.toString());
}
}
提示:此处的切面类可以不取id.
5、Spring的AOP 中注解通知
5.1. 前置通知
/**
* 前置通知
* @param joinPoint
*/
@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")
public void checkPrivilege(JoinPoint joinPoint){
System.out.println("权限校验..." + joinPoint.toString());
}
5.2. 后置通知
@Aspect
public class MyAspect {
/**
* 前置通知
* @param joinPoint
*/
@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")
public void checkPrivilege(JoinPoint joinPoint){
System.out.println("权限校验..." + joinPoint.toString());
}
@AfterReturning(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))",returning="result")
public void afterReturning(Object result){
System.out.println("后置通知:" + result);
}
}
5.3. 环绕通知
@Around("execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))")
public Object after(ProceedingJoinPoint joinpoint) throws Throwable{
System.out.println("环绕通知前增强");
Object obj = joinpoint.proceed();
System.out.println("环绕通知后增强");
return obj;
}
5.4. 异常通知
@AfterThrowing(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))",throwing="ex")
public void afterThrowing(Exception ex){
System.out.println("抛出异常通知");
}
5.5. 最终通知
@After("execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))")
public void after(){
System.out.println("最终通知");
}
5.6. PointCut注解(了解)
作用:用于定义切入点表达式的一个注解。
@Component("myAspectAnnotation")
@Aspect
public class MyAspect {
/**
* 前置通知
* @param joinPoint
*/
@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")
public void checkPrivilege(JoinPoint joinPoint){
System.out.println("权限校验..." + joinPoint.toString());
}
@AfterReturning(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))",returning="result")
public void afterReturning(Object result){
System.out.println("后置通知:" + result);
}
@Around("execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))")
public Object aroung(ProceedingJoinPoint joinpoint) throws Throwable{
System.out.println("环绕通知前增强");
Object obj = joinpoint.proceed();
System.out.println("环绕通知后增强");
return obj;
}
// @AfterThrowing(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))",throwing="ex")
@AfterThrowing(value="MyAspect.pointcut()",throwing="ex")
public void afterThrowing(Exception ex){
System.out.println("抛出异常通知");
}
// @After("execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))")
@After("MyAspect.pointcut()")
public void after(){
System.out.println("最终通知");
}
@Pointcut("execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))")
public void pointcut(){
}
}
spring框架总结(03)重点介绍(Spring框架的第二种核心掌握)的更多相关文章
- Spring官方文档翻译——15.1 介绍Spring Web MVC框架
Part V. The Web 文档的这一部分介绍了Spring框架对展现层的支持(尤其是基于web的展现层) Spring拥有自己的web框架--Spring Web MVC.在前两章中会有介绍. ...
- 是时候给大家介绍 Spring Boot/Cloud 背后豪华的研发团队了。
看了 Pivotal 公司的发展历史,这尼玛就是一场商业大片呀. 我们刚开始学习 Spring Boot 的时候肯定都会看到这么一句话: Spring Boot 是由 Pivotal 团队提供的全新框 ...
- 【转帖】是时候给大家介绍 Spring Boot/Cloud 背后豪华的研发团队了。
是时候给大家介绍 Spring Boot/Cloud 背后豪华的研发团队了. 2019/01/03 http://www.ityouknow.com/springboot/2019/01/03/spr ...
- Spring入门篇——第7章 Spring对AspectJ的支持
第7章 Spring对AspectJ的支持 介绍Spring对AspectJ的支持 7-1 AspectJ介绍及Pointcut注解应用 实例 完成了在xml文件的配置 7-2 Advice定义及实例 ...
- 带你手写基于 Spring 的可插拔式 RPC 框架(一)介绍
概述 首先这篇文章是要带大家来实现一个框架,听到框架大家可能会觉得非常高大上,其实这和我们平时写业务员代码没什么区别,但是框架是要给别人使用的,所以我们要换位思考,怎么才能让别人用着舒服,怎么样才能让 ...
- 关于如何介绍spring框架。
一.介绍Spring 1.Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架. 2.概念:轻量级的IOC(控制反转或者依赖注入).AOP(面向切面或者面向方面) ...
- Spring框架学习03——Spring Bean 的详解
1.Bean 的配置 Spring可以看做一个大型工厂,用于生产和管理Spring容器中的Bean,Spring框架支持XML和Properties两种格式的配置文件,在实际开发中常用XML格式的配置 ...
- Spring4- 01 - Spring框架简介及官方压缩包目录介绍- Spring IoC 的概念 - Spring hello world环境搭建
一. Spring 框架简介及官方压缩包目录介绍 主要发明者:Rod Johnson 轮子理论推崇者: 2.1 轮子理论:不用重复发明轮子. 2.2 IT 行业:直接使用写好的代码. Spring 框 ...
- Spring框架IOC和AOP介绍
说明:本文部分内容参考其他优秀博客后结合自己实战例子改编如下 Spring框架是个轻量级的Java EE框架.所谓轻量级,是指不依赖于容器就能运行的.Struts.Hibernate也是轻量级的. 轻 ...
随机推荐
- postgresql如何维护WAL日志/归档日志
WAL日志介绍 wal全称是write ahead log,是postgresql中的online redo log,是为了保证数据库中数据的一致性和事务的完整性.而在PostgreSQL 7中引入的 ...
- C++中4个类型转换相关的关键字/特点/应用场合
reinterpret_cast是C++里面的一个强制类型转换符,能够将任何的指针类型转换成其他的任何指针类型:能够将任何的整数类型转换成指针类型,反之亦然:滥用reinterpret_cast强制类 ...
- Vuejs 页面的区域化与组件封装
组件的好处 当我用vue写页面的时候,大量的数据页面渲染,引入组件简化主页面的代码量,当代码区域块代码差不多相同时,组件封装会更加简化代码.组件是Vue.js最强大的功能之一. 组件可以扩展HTML元 ...
- ActiveMQ笔记——技术点汇总
目录 · Introduction to ActiveMQ · Installing ActiveMQ · Message-oriented middleware · JMS specificatio ...
- 怎么调用api接口
api的简单调用,调用api的方法 方法一:用前端方法调用api 完整代码: <!DOCTYPE html> <html lang="en"> <he ...
- Domain Driven Design
在Spring官网的第一个tutorial中看到了这种 设计模式 Domain Driven Design 找到了篇介绍这个得文章: What is Domain Driven Design? &qu ...
- Java 关于路径
在eclipse中如果没有指名文件的路径的话,系统默认是与src同一级别的目录路径!
- KVM虚拟化主机安装
KVM虚拟化主机安装 最小化安装CentOS6.X或者CentOS7.X,RHEL6.X以上系列建议建议选择安装最小虚拟化主机 如果要安装桌面可以先选择最小化虚拟主机,再选择Gnome桌面包 安装过程 ...
- win8下安装VC6出现兼容性问题的解决办法
重装系统之后(win8的系统),发现VC6安装出现兼容性问题,花了一些时间解决,有出现的问题都差不多在下面链接的总结中,写的很详细: http://www.docin.com/p-1126120829 ...
- 201521123042 《java程序设计》 第八周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. ①泛型定义:泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展, ...