- 浏览: 85430 次
- 性别:
- 来自: 西安
最新评论
-
xuhang1128:
good
Spring源码解析 BeanPostProcessor的实现 -
zhudaokun:
呵呵……好帖,收藏一下
Spring源码解析1 IOC容器的初始化
参考《Spring高级程序设计》
引入是Spring提供的AOP功能的重要组成部分。使用引入可以动态地在现有的对象中添加新的功能。当我们在现有的对象中添加的功能是一个横切关注点而用传统的面向对象方法难以实现时,我们就可以利用引入动态的添加该功能了。
Spring文档中列举了两个典型的引入用法:对象锁定和对象篡改检测。
我们主要对对象篡改检测进行分析:
现在我们构建一个统计信息收集框架。篡改检测的逻辑被封装在CallTracker接口中,他的一个实现连同自动篡改检测的拦截逻辑被一起引入到合适的对象中。
CallTracker接口
package com.spring.ch06.service; public interface CallTracker { void markNormal(); void markFailing(); int countNormalCalls(); int countFailingCalls(); String describe(); }
CallTracker接口的一个实现
package com.spring.ch06.service; public class DefaultCallTracker implements CallTracker { private int normalCalls; private int failingCalls; @Override public int countFailingCalls() { return failingCalls; } @Override public int countNormalCalls() { return normalCalls; } @Override public String describe() { return toString(); } @Override public void markFailing() { this.failingCalls++; } @Override public void markNormal() { this.normalCalls++; } public String toString(){ final StringBuilder sb=new StringBuilder(); sb.append("DefaultCallTracker"); sb.append("{normalCalls=").append(this.normalCalls); sb.append(",failingCalls=").append(this.failingCalls); sb.append("}"); return sb.toString(); } }
创建一个方面
package com.spring.ch06.service; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.DeclareParents; import org.aspectj.lang.annotation.Pointcut; @Aspect public class CallTrackerAspect { @Pointcut("execution(* com.spring.ch06.service.*.*(..))") private void serviceCall(){} /* * 声明我们将使用DefaultCallTracker实现把CallTracker接口引入到com.spring.ch06.service * 包下的所有的类中 */ @DeclareParents( value="com.spring.ch06.service.*", defaultImpl=DefaultCallTracker.class) public static CallTracker mixin; /* * serviceCall()代表@Pointcut,而this(tracker)将匹配实现了CallTracker接口的对象上所有方法 * 执行。SpringAOP会将追踪器参数绑定到被通知的对象上。 */ @AfterReturning( value="serviceCall()&&this(tracker)", argNames="tracker") public void normallCall(CallTracker tracker){ tracker.markNormal(); } @AfterThrowing( value="serviceCall()&&this(tracker)", throwing="t", argNames="tracker,t") public void failingCall(CallTracker tracker,Throwable t){ tracker.markFailing(); } }
现有对象:
package com.spring.ch06.service; import com.spring.ch06.common.User; public interface UserService { public void login(String username); void setAdministratorUsername(String administratorUsername); User findById(long id); }
package com.spring.ch06.service; import com.spring.ch06.common.SecurityContext; import com.spring.ch06.common.User; public class DefaultUserService implements UserService{ private String administratorUsername = "janm"; public void login(String username) { if (this.administratorUsername.equals(username)) { SecurityContext.setCurrentUser(username); } } public void setAdministratorUsername(String administratorUsername) { this.administratorUsername = administratorUsername; } public User findById(long id) { User user = new User(); user.setUsername(String.valueOf(id)); user.setPassword("Very secret password"); return user; } }
package com.spring.ch06.service; import java.math.BigDecimal; import java.util.Date; public interface StockService { long getStockLevel(String sku); long getPredictedStockLevel(String sku); void applyDiscounts(Date cutoffDate, BigDecimal maximumDiscount); }
package com.spring.ch06.service; import java.util.Date; import java.math.BigDecimal; /** * @author janm */ public class DefaultStockService implements StockService { public long getStockLevel(String sku) { try { Thread.sleep(2000L); } catch (InterruptedException ignored) { } return getPredictedStockLevel(sku) / 2L; // return ((StockService)AopContext.currentProxy()).getPredictedStockLevel(sku) / 2L; } public long getPredictedStockLevel(String sku) { return 6L * sku.hashCode(); } public void applyDiscounts(Date cutoffDate, BigDecimal maximumDiscount) { // do some work } }
测试:
package com.spring.ch06; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.math.BigDecimal; import java.util.*; import com.spring.ch06.service.CallTracker; import com.spring.ch06.service.StockService; import com.spring.ch06.service.UserService; public class IntroductionDemo { public static void main(String[] args) { //ApplicationContext ac=new ClassPathXmlApplicationContext("/introductiondemo1.xml"); ApplicationContext ac=new ClassPathXmlApplicationContext("/introductiondemo2.xml"); UserService userService=(UserService)ac.getBean("userService"); describeTracker(userService); userService.login("janm"); userService.setAdministratorUsername("x"); describeTracker(userService); StockService stockService=(StockService)ac.getBean("stockService"); describeTracker(stockService); try{ stockService.getStockLevel(null); }catch(Exception ignored){ } System.out.println(stockService.getStockLevel("ABC")); stockService.applyDiscounts(new Date(), new BigDecimal("10.0")); describeTracker(stockService); } public static void describeTracker(Object o){ CallTracker t=(CallTracker)o; System.out.println(t.describe()); } }
配置文件:采用两种方式:注解和AOP命名空间配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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 "> <aop:aspectj-autoproxy/> <bean id="userService" class="com.spring.ch06.service.DefaultUserService"/> <bean id="stockService" class="com.spring.ch06.service.DefaultStockService"/> <bean class="com.spring.ch06.service.CallTrackerAspect"/> <!-- 使用CallTrackerAspect的userService bean类型是JdkDynamicAopProxy,它不是一个DefaultUserService 的实例。这个代理双双实现了UserService接口和CallTracker混入体接口。它拦截对所有方法的调用并将UserService 接口上的调用委托给DefaultUserService.这个代理也创建了一个DefaultCallTracker(在@DeclareParents注解中被定义) 的实例并将CallTracker接口上所有的调用委托给DefaultCallTracker实例。 --> </beans>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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 "> <bean id="userService" class="com.spring.ch06.service.DefaultUserService"/> <bean id="stockService" class="com.spring.ch06.service.DefaultStockService"/> <bean id="aspectBean" class="com.spring.ch06.service.AspectBean"/> <!-- AOP命名空间中的引入 (引入通过代理被通知对象,向已有对象中添加额外的方法, 并让代理实现那些接口,它是我们在原有是想上声明的接口)--> <aop:config> <aop:aspect id="aroundAspect" ref="aspectBean"> <aop:declare-parents types-matching="com.spring.ch06.service.*" implement-interface="com.spring.ch06.service.CallTracker" default-impl="com.spring.ch06.service.DefaultCallTracker"/> <aop:after-returning method="normalCall" arg-names="tracker" pointcut="execution(* com.spring.ch06.service.*.*(..)) and this(tracker)"/> <aop:after-throwing method="failingCall" arg-names="tracker" pointcut="execution(* com.spring.ch06.service.*.*(..)) and this(tracker)"/> </aop:aspect> </aop:config> <!-- 使用CallTrackerAspect的userService bean类型是JdkDynamicAopProxy,它不是一个DefaultUserService 的实例。这个代理双双实现了UserService接口和CallTracker混入体接口。它拦截对所有方法的调用并将UserService 接口上的调用委托给DefaultUserService.这个代理也创建了一个DefaultCallTracker(在@DeclareParents注解中被定义) 的实例并将CallTracker接口上所有的调用委托给DefaultCallTracker实例。 --> </beans>
package com.spring.ch06.service; import org.aspectj.lang.JoinPoint; import com.spring.ch06.common.User; public class AspectBean { public void normalCall(CallTracker tracker){ tracker.markNormal(); } public void failingCall(CallTracker tracker){ tracker.markFailing(); } }
发表评论
-
Spring MVC 整体的流程
2011-04-30 13:17 2268DispatcherServlet(DispatcherSer ... -
Spring ApplicationContext
2010-10-06 13:07 3927ApplicationContext是一个IoC容器,但它扩展 ... -
Spring属性编辑器
2010-10-06 12:03 3231什么是属性编辑器,作用? * 自定义属性编辑器,spring配 ... -
Spring源码解析 BeanPostProcessor的实现
2010-10-02 21:45 2494BeanPostProcessor是使用IoC容器时经常使用会 ... -
Spring源码解析 lazy-init属性和预实例化
2010-10-02 19:02 3391默认情况下会在容器启动时初始化bean, 但是我们可以指定Be ... -
Spring源码解析 依赖注入
2010-10-02 18:35 6356当IoC容器的初始化完毕后,我们就要接触IoC容器的核心功能: ... -
Spring源码解析3 IOC容器的初始化
2010-10-02 13:12 1544上一次我们了解BeanDefinition的在载入和解析,现在 ... -
Spring源码解析 2 IOC容器的初始化
2010-10-02 12:06 3007前面我们分析了:IoC容器的第一个步骤BeanDefiniti ... -
Spring源码解析1 IOC容器的初始化
2010-10-01 22:03 2093参考《Spring技术内幕》一书: IoC容器的基本接 ... -
BeanFactoryPostProcessor类的运用
2010-09-07 10:48 5126package com.spring.ch04; imp ...
相关推荐
2.1 运用Spring Boot 19 2.1.1 查看初始化的Spring Boot新项目 21 2.1.2 Spring Boot项目构建过程解析 24 2.2 使用起步依赖 27 2.2.1 指定基于功能的依赖 28 2.2.2 覆盖起步依赖引入的传递依赖 29 2.3 ...
2.1 运用Spring Boot 19 2.1.1 查看初始化的Spring Boot新项目 21 2.1.2 Spring Boot项目构建过程解析 24 2.2 使用起步依赖 27 2.2.1 指定基于功能的依赖 28 2.2.2 覆盖起步依赖引入的传递依赖 29 ...
把Spring 增量地引入现有的项目中是十分容易的。 l Spring 从设计之初就是要帮助你写出易于测试的代码。Spring 是测试驱动项目的一个理 想框架。 l Spring 是一个日益重要的集成技术,它的角色已得到一些大...
运用JSP spring实现的分页程序范例,含源代码,界面方面使用了EXTJS库配合,EXT的风格那当然没话说了,很漂亮了,由于空间问题web-inf/lib里的jar文件未引入,本项目是在struts2 hibernate spring构架下的,所以需要...
1 运用 Spring Boot 19 2 . 1 . 1 查看初始化的 Spring soot 新项目 21 21 . 2 Spring Boot 项目构建过程解析 24 2 . 2 使川起步依赖, 27 2 . 2 . 1 指定基于功能的依赖 28 2 . 2 . 2 覆盖起步依赖引入的传递依赖...
在Web端的SSH框架整合中Spring主要负责数据库处理,而引入MyBatis后二者的集成使用效果更佳,下面我们就来详解Java的MyBatis框架和Spring框架的整合运用
积分商城系统是一个综合运用Spring、MySQL和Redis等技术构建的全功能商城解决方案,为用户和管理员提供了便捷、安全和可靠的购物和管理体验。通过积分机制的引入,系统在用户激励和促销方面具备独特的优势,为商家和...
主要给大家介绍了关于Spring Boot优雅使用RocketMQ的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring Boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
不过要想灵活运用Spring MVC来应对大多数的Web开发,就必须要掌握它的配置及原理。 一、Spring MVC环境搭建:(Spring 2.5.6 + Hibernate 3.2.0) 1. jar包引入 Spring 2.5.6:spring.jar、spring-webmvc.jar、...
SpringCloud微服务项目 写一个中型的游戏分享网站 后端技术运用Spring+SpringMVC+SpringBoot + SpringCloud微服务全家桶 数据库中间件Mybatis 缓存数据库Redis(未来可能引入MongoDB做消息缓存及日志处理) 数据库...
系统后台模块采用 MVC 与 前后端分离 的架构思想,引入了 spring boot 2 框架构建 Web 项目,以及提供 json 格式的数据接口给予前端进行接口调用,从而实现前后端分离的架构思想。前端采用 layUI 作为前端 UI 框架,...
②后端采用主流的ssm(Spring+SpringMVC+MyBatis)框架,spring作为控制反转(ioc)和面向切面(aop)的容器框架,Spring MVC主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。...
1 运用 Spring Boot 19 2 . 1 . 1 查看初始化的 Spring soot 新项目 21 21 . 2 Spring Boot 项目构建过程解析 24 2 . 2 使川起步依赖, 27 2 . 2 . 1 指定基于功能的依赖 28 2 . 2 . 2 覆盖起步依赖引入的传递依赖...
2.1 运用 Spring Boot ..................................... 19 2.1.1 查看初始化的 Spring Boot 新项目 .......................................... 21 2.1.2 Spring Boot 项目构建过程 解析 .....................
学习者可以根据自己的需求,在现有基础上进行功能拓展或定制开发,如增加书籍推荐算法、引入更多支付方式、优化用户界面等。 总之,这个基于Spring Boot的网上书城毕业设计项目是一个宝贵的学习资源,无论是对于...
SSM(Spring + Spring MVC + MyBatis)框架作为Java开发中的黄金组合,为开发者提供了强大的技术支持和丰富的功能。本系列资料将带您从零基础开始,逐步掌握SSM的核心技术和最佳实践,助您在Java Web开发领域更上一...
项目中,我们充分运用了Spring Boot的轻量级、快速开发的特点,结合前端技术,构建了一个用户友好的界面。平台包含了用户管理、心理测试、在线辅导、资讯发布等多个模块,能够满足不同用户群体的需求。学生可以通过...
ostp户外运动后台构建中,运用了javaweb的ssm三大框架160818:删除多余的前端代码失败。等待后续有时间进行整改160820:引入了新的前端ui(可能存在乱码问题),对控制器进行了部分修改。控制器引入iframe包含文件...
Spring Initializr 初始化Spring Boot 项目..........................101.3 小结 .........................................................18第 2 章 开发第一个应用程序 ....................192.1 运用 ...
Spring框架的引入,使得系统的业务逻辑与数据访问层得到了有效分离,提高了代码的可读性和可复用性。SpringMVC则负责处理用户请求与响应,保证了前后端的良好交互。MyBatis则提供了高效、灵活的数据库操作,为系统的...