`
imaginecup
  • 浏览: 87413 次
  • 性别: 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之AOP注解之引入通知

    本篇文章将深入探讨Spring AOP中的注解引入通知,以及如何利用它们来增强代码的可维护性和模块化。 首先,我们要理解什么是“引入通知”(Introduction Advice)。引入通知是Spring AOP的一种特殊类型的通知,它...

    spring AOP的运用

    在本文中,我们将深入探讨Spring AOP的运用,并结合源码分析其工作原理。 首先,了解AOP的基本概念: 1. 切面(Aspect):切面是关注点的模块化,这些关注点通常是跨越多个对象的横切关注点,例如事务管理、日志...

    Spring框架的运用

    - **注解配置**:随着版本发展,Spring引入了注解,允许在类和方法上直接声明Bean和依赖。如`@Component`、`@Autowired`等。 - **Java配置**:Spring 3.0引入了Java配置,可以在Java类中定义配置,增强了代码的...

    spring的运用

    在“spring的运用”这个主题中,我们将深入探讨Spring框架在实际开发中的应用。 1. **控制反转(IoC)**: IoC是Spring的核心概念,它通过容器来管理对象的创建和依赖关系。开发者无需手动创建对象,而是将对象配置...

    spring源码包.zip

    通过对这些模块的源码分析,我们可以深入了解Spring如何实现其强大的功能,并能更好地运用到实际项目中,提升代码质量和可维护性。无论是新手还是经验丰富的开发者,理解Spring的源码都将是一次宝贵的进阶之旅。

    Spring框架jar包全

    在4.1.6版本中,Spring引入了一些改进和新特性,例如: - 改进了SpEL(Spring Expression Language),增强了表达式评估能力。 - 对WebSocket的支持得到增强,提供了更好的异步通信机制。 - Spring Data项目持续...

    spring4 资料

    本资料主要围绕Spring4、Spring Security4以及Spring AOP这三大核心模块展开,旨在帮助开发者深入理解和熟练运用这些技术。 首先,Spring4作为Spring框架的第四代版本,引入了诸多改进和新特性。它提升了性能,尤其...

    spring5.0.1稳定版

    Spring框架是Java开发中不可或缺的一部分,它以其模块化、易用性和灵活性著称。Spring 5.0.1是该框架的一个稳定版本,为开发者提供了更...通过深入理解并熟练运用Spring框架,开发者可以构建出更加灵活、可维护的系统。

    spring2.5中文文档

    Spring框架是Java开发中不可或缺的一部分,它以其模块化、易用...通过这份文档,开发者可以深入理解Spring的工作原理,并能熟练运用到自己的项目中。对于学习和掌握Spring 2.5,这份中文文档无疑是一份宝贵的参考资料。

    spring-framework-1.0-m1.zip源码

    本文将深入探讨Spring 1.0源码,帮助读者理解其设计理念和核心机制,以便更好地运用和定制这一经典框架。 一、Spring框架概述 Spring框架是Rod Johnson在2003年推出的,它旨在简化Java企业级应用程序的开发。1.0...

    Spring框架开发参考中文手册

    《Spring框架开发参考中文手册》是一本专门为Java开发者设计的指南,旨在帮助他们深入理解和熟练运用Spring框架进行软件开发。Spring作为Java企业级应用开发的主流框架,以其强大的功能、灵活的设计和广泛的社区支持...

    spring-tx-5.0.0.0.RELEASE.jar_java开发_spring-tx-5.0.0_

    《深入解析Spring TX 5.0.0:构建高效事务管理》 在Java开发领域,Spring框架以其强大的功能和灵活性而备受青睐。其中,Spring TX模块是Spring框架...理解并熟练运用Spring TX,将有助于提升项目的稳定性和可维护性。

    spring2,spring3 相关技术文档

    Spring框架是Java开发中不可或缺的重要组成部分,它以其强大的IoC(Inversion of Control,控制反转)和AOP...因此,无论是初学者还是经验丰富的开发者,都应该充分利用这些资源,深入理解并熟练运用Spring框架。

    spring+spring mvc+mybatis框架整合实现超市货物管理系统

    在该项目中,我们需要设置相关的Maven或Gradle依赖,确保Spring、Spring MVC和MyBatis等库的引入,并配置数据库连接。 总的来说,"spring+spring mvc+mybatis框架整合实现超市货物管理系统"是一个涵盖后端开发基础...

    spring MVC配置详解

    要想灵活运用 Spring MVC 来应对大多数的 Web 开发,就必须要掌握它的配置及原理。 一、Spring MVC 环境搭建 1. jar 包引入 在使用 Spring MVC 之前,需要引入相应的 jar 包,包括 Spring 2.5.6 和 Hibernate ...

    spring框架jar包

    同时,理解每个jar包的作用和如何在项目中运用它们,是提升Spring框架使用效率的重要途径。通过学习Spring的IoC、AOP、MVC等核心概念,开发者可以更好地理解和利用这个强大的框架,创建出高效、可维护的Java应用。

    spring2.0 中文教程

    通过阅读《Spring 2.0中文教程》中的内容,开发者可以深入理解这些概念,并学会如何在实际项目中运用Spring框架。这本书将帮助读者掌握Spring的核心功能,提高开发效率,打造更加健壮的企业级应用。

    Spring4.0源代码

    Spring4.0版本是其发展历程中的一个重要里程碑,引入了许多新特性并优化了原有功能。下面我们将深入探讨Spring4.0源代码中的关键知识点。 1. **控制反转(IoC)**:Spring的核心特性之一是IoC,通过容器管理对象的...

    Spring.pdf

    7. Spring 框架源码是经典学习范例:Spring 的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对 Java 设计模式灵活运用以及对 Java 技术的高深造诣。 使用 Spring 框架的步骤: 1. 创建 Maven 项目:指定...

Global site tag (gtag.js) - Google Analytics