`
imaginecup
  • 浏览: 85430 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

Spring 引入的运用

阅读更多

参考《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 boot实战.pdf高清无水印

    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 ...

    Spring Boot实战 ,丁雪丰 (译者) 中文版

    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 Framework 概述.rar

    把Spring 增量地引入现有的项目中是十分容易的。 l Spring 从设计之初就是要帮助你写出易于测试的代码。Spring 是测试驱动项目的一个理 想框架。 l Spring 是一个日益重要的集成技术,它的角色已得到一些大...

    JSP spring实用的分页程序源码 EXT.rar

    运用JSP spring实现的分页程序范例,含源代码,界面方面使用了EXTJS库配合,EXT的风格那当然没话说了,很漂亮了,由于空间问题web-inf/lib里的jar文件未引入,本项目是在struts2 hibernate spring构架下的,所以需要...

    SpringBoot实战(第4版)清晰版

    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 覆盖起步依赖引入的传递依赖...

    详解Java的MyBatis框架和Spring框架的整合运用

    在Web端的SSH框架整合中Spring主要负责数据库处理,而引入MyBatis后二者的集成使用效果更佳,下面我们就来详解Java的MyBatis框架和Spring框架的整合运用

    基于spring的前后端一体化积分商城系统

    积分商城系统是一个综合运用Spring、MySQL和Redis等技术构建的全功能商城解决方案,为用户和管理员提供了便捷、安全和可靠的购物和管理体验。通过积分机制的引入,系统在用户激励和促销方面具备独特的优势,为商家和...

    Spring Boot优雅使用RocketMQ的方法实例

    主要给大家介绍了关于Spring Boot优雅使用RocketMQ的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring Boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

    Spring MVC 框架搭建配置方法及详解

    不过要想灵活运用Spring MVC来应对大多数的Web开发,就必须要掌握它的配置及原理。 一、Spring MVC环境搭建:(Spring 2.5.6 + Hibernate 3.2.0) 1. jar包引入  Spring 2.5.6:spring.jar、spring-webmvc.jar、...

    Spring Cloud + React+ Mysql写的一个中型的游戏分享网站源码.zip

    SpringCloud微服务项目 写一个中型的游戏分享网站 后端技术运用Spring+SpringMVC+SpringBoot + SpringCloud微服务全家桶 数据库中间件Mybatis 缓存数据库Redis(未来可能引入MongoDB做消息缓存及日志处理) 数据库...

    基于SpringBoot实现的可视化学生管理系统源码.zip

    系统后台模块采用 MVC 与 前后端分离 的架构思想,引入了 spring boot 2 框架构建 Web 项目,以及提供 json 格式的数据接口给予前端进行接口调用,从而实现前后端分离的架构思想。前端采用 layUI 作为前端 UI 框架,...

    # community community for study 本项目偏后端练习运用。 > 使用前请先导入community

    ②后端采用主流的ssm(Spring+SpringMVC+MyBatis)框架,spring作为控制反转(ioc)和面向切面(aop)的容器框架,Spring MVC主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。...

    SpringBoot实战(第4版)清晰版,外送惊喜入口

    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 覆盖起步依赖引入的传递依赖...

    springBoot实战4.0 高清版

    2.1 运用 Spring Boot ..................................... 19 2.1.1 查看初始化的 Spring Boot 新项目 .......................................... 21 2.1.2 Spring Boot 项目构建过程 解析 .....................

    Java毕业设计-基于springboot开发的网上书城--论文-附毕设源代码+说明文档.rar

    学习者可以根据自己的需求,在现有基础上进行功能拓展或定制开发,如增加书籍推荐算法、引入更多支付方式、优化用户界面等。 总之,这个基于Spring Boot的网上书城毕业设计项目是一个宝贵的学习资源,无论是对于...

    使用主流框架组合SSM开发,并引入新技术,全面丰富的一个商城项目.zip

    SSM(Spring + Spring MVC + MyBatis)框架作为Java开发中的黄金组合,为开发者提供了强大的技术支持和丰富的功能。本系列资料将带您从零基础开始,逐步掌握SSM的核心技术和最佳实践,助您在Java Web开发领域更上一...

    Java毕业设计-基于springboot开发的高校心理教育辅导设计与实现-毕业论文(附毕设源代码).rar

    项目中,我们充分运用了Spring Boot的轻量级、快速开发的特点,结合前端技术,构建了一个用户友好的界面。平台包含了用户管理、心理测试、在线辅导、资讯发布等多个模块,能够满足不同用户群体的需求。学生可以通过...

    ostp:基于引导程序,spring,springmvc,mybatis,spring security的后台管理系统

    ostp户外运动后台构建中,运用了javaweb的ssm三大框架160818:删除多余的前端代码失败。等待后续有时间进行整改160820:引入了新的前端ui(可能存在乱码问题),对控制器进行了部分修改。控制器引入iframe包含文件...

    String Boot实战

    Spring Initializr 初始化Spring Boot 项目..........................101.3 小结 .........................................................18第 2 章 开发第一个应用程序 ....................192.1 运用 ...

    Java毕业设计-基于ssm框架开发的学生竞赛模拟系统-附毕设源代码+说明文档.rar

    Spring框架的引入,使得系统的业务逻辑与数据访问层得到了有效分离,提高了代码的可读性和可复用性。SpringMVC则负责处理用户请求与响应,保证了前后端的良好交互。MyBatis则提供了高效、灵活的数据库操作,为系统的...

Global site tag (gtag.js) - Google Analytics