http://blog.csdn.net/21aspnet/article/details/51386557

1.IOC装配Bean

参考【spring实战4 2.2】,作者提倡无XML配置化。

1.1接口只有一个现实类

可以自动装配

 package demo;

 public interface CompactDisc {
void play();
}

实现类

 package demo;

 import org.springframework.stereotype.Component;

 @Component 
6 public class SgtPeppers implements CompactDisc{
private String title = "Sgt. Pepper's Lonely Hearts Club Band";
private String artist = "http://blog.csdn.net/unix21"; public void play() {
System.out.println("【非常醒目SgtPeppers 】>>>>>>>>>>>>>>>>>Playing " + title + " by " + artist);
}
}

配置类

 package demo;

 import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; @Configuration
@ComponentScan
public class CDPlayerConfig { }

单元测试类

 package demo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
@Autowired
@Qualifier("spn")
private CompactDisc cd; @Test
public void play() {
cd.play();
}
}

测试结果

1.2 接口有多个实现类

【参考 Spring实战4 3.3】
故意再写一个实现类

 package demo;

 import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component; @Component
public class SgtPeppersNew implements CompactDisc{
private String title = "Sgt. Pepper's Lonely Hearts Club Band";
private String artist = "http://blog.csdn.net/unix21"; public void play() {
System.out.println("【非常醒目SgtPeppersNew 】>>>>>>>>>>>>>>>>>Playing " + title + " by " + artist);
}
}

此时有两个实现类,如果这时执行单元测试类的时候,测试类不知道注入(DI)那个实现类,所以会报错。

两种解决方案:1,加@Primary 首选标识的bean  2, 使用@Qualifier注解@Qualifier("SgtPeppersNew"), 改变@Component("SgtPeppersNew")   或者@Qualifier 注解中用实现类,但id是小写@Qualifier("sgtPeppersNew"),不需要改变@Component

 package demo;

 import org.springframework.stereotype.Component;

 @Component
public class SgtPeppersNew implements CompactDisc{
private String title = "Sgt. Pepper's Lonely Hearts Club Band";
private String artist = "http://blog.csdn.net/unix21"; public void play() {
System.out.println("【非常醒目SgtPeppersNew 】>>>>>>>>>>>>>>>>>Playing " + title + " by " + artist);
}
}
 package demo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
@Autowired
@Qualifier("sgtPeppersNew")
private CompactDisc cd; @Test
public void play() {
cd.play();
}
}

打印结果

1.3 为组件扫描的bean命名  

【参考 Spring实战4  2.2.2】

 import org.springframework.stereotype.Component;  

 @Component("spn")
public class SgtPeppersNew implements CompactDisc {
     @Autowired
@Qualifier("spn")
private CompactDisc cd;

也可以使用@Named效果是一样的,这是java依赖注入规范

 import javax.inject.Named;  

 @Named("spn")
public class SgtPeppersNew implements CompactDisc {

1.4 设定组件扫描的指定包

【参考 Spring实战4  2.2.3】

如果@ComponentScan默认不设置只扫描配置类所在的包作为基础包

@Configuration
@ComponentScan("blog.csdn.net.unix21")
public class CDPlayerConfigTest

设置@ComponentScan的value属性就可以指明包名称。

如果想更清晰的表明设置的是基础包
@ComponentScan(basePackages="指定包")

指定多个

@ComponentScan(basePackages={"指定包1","指定包2"})

也可以将其指定为包中所包含的类或者接口

@ComponentScan(basePackages={"XXX.class","XX.class"})

1.5 自动装配

【参考 Spring实战4  2.2.4】

声明自动装配需要@Autowired注解

1.5.1 在构造方法上使用自动装配

 package demo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfigTest.class)
public class CDPlayerFunTest {
private CompactDisc cd;
@Autowired
@Qualifier("spn")
public void CDPlayer(CompactDisc cd) {
this.cd = cd;
} @Test
public void play() {
cd.play();
System.out.println("【占位符】CDPlayerFunTest");
}
}

另一种写法

 @Component
public class CDPlayer implements MediaPlayer {
private CompactDisc cd; @Autowired
public CDPlayer(@Qualifier("spn")CompactDisc cd) {
this.cd = cd;
} public void play() {
cd.play();
} }

1.5.2 在属性Setter方法上使用自动装配

 @Component
public class CDPlayer implements MediaPlayer {
private CompactDisc cd; @Autowired
@Qualifier("spn")
public void setCompactDisc(CompactDisc cd) {
this.cd = cd;
} public void play() {
cd.play();
}
}

避免异常声明  @Autowired(required = false),如果没有匹配的bean,Spring会让这个bean处于未装配转态,但是需要谨慎对待这个设置,代码需要做null检查。

@Autowired是Spring特有的注解,可以替换为@Inject,@Inject来源自Jave依赖注入规范。

1.6 创建自定义的限定符

【参考 Spring实战4  3.3.2】

@Component
@Qualifier("cold")
public class IceCream implements CompactDisc { private String title = "Sgt. Pepper's Lonely Hearts Club Band";
private String artist = "The Beatles"; public void play() {
System.out.println("【非常醒目 IceCream】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Playing " + title + " by " + artist);
}
}
 @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=CDPlayerConfigTest.class)
public class CDPlayerLogTest { @Autowired
private MediaPlayer player; @Autowired
@Qualifier("sp")
private CompactDisc cd; @Autowired
@Qualifier("cold")
private CompactDisc cd2; @Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
} @Test
public void play() {
player.play();
cd.play();
cd2.play();
}
}

好处:这样做的好处限定符不耦合类名,所以可以随意重构类名。

问题:重复的限定符出现在多个类上这是不允许的,因为Java不允许同一个条目上重复出现相同类型的多个注解

注意:此时我用本地测试时发现  private MediaPlayer player;  这个player 并不能注入到测试类中,需要以后解决。

解决:注意其实CDplayer 也是需要创建的组件类,所以也要加上@Component

1.7 使用自定义限定符注解

针对上述问题可以创建自定义的限定符注解。

 @Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Target({ElementType.CONSTRUCTOR,ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})//定义注解的作用目标**作用范围字段、枚举的常量/方法
@Qualifier
public @interface Cold {}
 @Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Target({ElementType.CONSTRUCTOR,ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})//定义注解的作用目标**作用范围字段、枚举的常量/方法
@Qualifier
public @interface Creamy {}
 @Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Target({ElementType.CONSTRUCTOR,ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})//定义注解的作用目标**作用范围字段、枚举的常量/方法
@Qualifier
public @interface Fruity {}
 @Component
@Cold
@Creamy
public class IceCream implements CompactDisc { private String title = "Spring 实现 第4版 读书笔记";
private String artist = "http://blog.csdn.net/unix21"; public void play() {
System.out.println("【非常醒目 IceCream】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Playing " + title + " by " + artist);
}
}
 @Component
@Cold
@Fruity
public class Popsicle implements CompactDisc { private String title = "Spring 实现 第4版 读书笔记";
private String artist = "http://blog.csdn.net/unix21"; public void play() {
System.out.println("【非常醒目 Popsicle】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Playing " + title + " by " + artist);
}
}
 @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfigTest.class)
public class CDPlayerLogTest { @Autowired
private MediaPlayer player; @Autowired
@Qualifier("sp")
private CompactDisc cd; @Autowired
@Cold
@Creamy
private CompactDisc cd2; @Autowired
@Cold
@Fruity
private CompactDisc cd3; @Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
} @Test
public void play() {
player.play();
cd.play();
cd2.play();
cd3.play();
}
}

1.8 bean的作用域

Spring定义了多重作用域,singleton单例,prototype原型等

参考:spring中scope作用域

singleton单例:整个应用中,只创建bean的一个实例,默认Spring上下文中所有的bean都是单例。

prototype原型:每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。

 @Component
public class Add implements AddI {
public int a=0; public void Add() {
a++;
} public void getA() {
System.out.println("【非常醒目 Add】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>a= " +a+"");
}
}
 public interface AddI {
void Add();
void getA();
}
 @Component
public class CDPlayer implements MediaPlayer { @Autowired
@Qualifier("sp")
private CompactDisc cd; @Autowired
private AddI a; public void play() {
System.out.println("【非常醒目 CDPlayer】>>>");
cd.play();
a.Add();
a.getA();
a.Add();
a.getA();
System.out.println("【非常醒目 CDPlayer】<<<");
}
}

测试用例

 @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfigTest.class)
public class CDPlayerLogTest { @Autowired
private MediaPlayer player; @Autowired
@Qualifier("sp")
private CompactDisc cd; @Autowired
@Cold
@Creamy
private CompactDisc cd2; @Autowired
@Cold
@Fruity
private CompactDisc cd3; @Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
} @Autowired
private AddI a; @Test
public void play() {
player.play();
cd.play();
cd2.play();
cd3.play();
a.getA();
}
}

再写一个多线程

 public class ClientThread extends Thread {  

     @Autowired
private AddI a; @Autowired
public ClientThread(AddI a) {
this.a = a;
} public void run() {
a.Add();
a.getA();
}
}

调用多线程

 @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfigTest.class)
public class SpringScopeTest { @Autowired
private AddI a; @Test
public void Scope() {
for (int i = 0; i < 10; i++) {
ClientThread t = new ClientThread(a);
t.start();
}
}
}

此时add实现类如下

@Component
//@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Add implements AddI{
public int a=0;
public void Add() {
// TODO Auto-generated method stub
a++;
} public void getA() {
// TODO Auto-generated method stub
System.out.println("【非常醒目 Add】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>a= " +a+"");
} }

如果使用单例模式则

补充说明:@Repository、@Service、@Controller 和 @Component将类标识为Bean,都是一样的,用在不同的地方而已。

2.AOP切面编程

定义接口

 public interface PerformanceI {
public void perform();
}

实现类

 import org.springframework.stereotype.Component;  

 @Component
public class Performance implements PerformanceI{
public void perform(){
System.out.println("【非常醒目 Performance perform 调用中】 By http://blog.csdn.net/unix21");
}
}

定义切面

 import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before; @Aspect
public class MyAspect {
@Before("execution(* com.demo.PerformanceI.perform(..))")
public void before(){
System.out.println("【非常醒目 [方法调用前] 】");
} @After("execution(* com.demo.PerformanceI.perform(..))")
public void after(){
System.out.println("【非常醒目 [方法调用后] 】");
} @AfterThrowing("execution(* com.demo.PerformanceI.perform(..))")
public void afterThrowing(){
System.out.println("【非常醒目 [方法异常后] 】");
}
}

配置文件

 import com.demo.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.demo")
public class AppConfig {
@Bean
public MyAspect myAspect() {
return new MyAspect();
} }

测试用例

 import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class MyTest { @Autowired
private PerformanceI p1; @Test
public void play() {
p1.perform();
}
}

此时在本地运行报错··········

 后来加入了  aopalliance.jar 包后解决问题 已经写入到 博客园内 问题3.

实现了方法调用前后的AOP效果。

这个Spring官方参考做的不错:http://docs.spring.io/spring/docs/4.2.5.RELEASE/javadoc-api/

这里选不同的版本:http://docs.spring.io/spring/docs/

4.3.2 创建环绕通知

哈哈此小结个人觉得挺有意思所以也就拿上来了。

环绕通知是最为强大的通知类型。它能够让你所编写的逻辑将被通知的目标方法完全包装起 来。实际上就像在一个通知方法中同时编写前置通知和后置通知。

环绕通知,直接上代码说事情。

 package concert;

 import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class MyAspect {
@Pointcut("execution(* concert.PerformanceI.perform(..))")
public void perform(){}
@Around("perform()")
public void watchPerformance(ProceedingJoinPoint jp){
try{
System.out.println("【非常醒目 [方法调用前] 】");
jp.proceed();
System.out.println("【非常醒目 [方法调用后] 】");
} catch (Throwable e){
System.out.println("【非常醒目 [方法异常后] 】");
}
}
}
@Around 是环绕通知的 注释,ProceedingJoinPoint 作为参数用来通知“想做的业务逻辑” 个人理解就是切点。
粘贴过来一张原图,是通过XML配置来实现AOP切面功能,跟上面 通过基于AspectJ注解 @EnableAspectJAutoProxy 引入是一个意思。

 

3.Spring MVC

DispatcherServlet是Spring MVC的核心,每当应用接受一个HTTP请求,由DispatcherServlet负责将请求分发给应用的其他组件。

首选给出一张Spring MVC的组件图,也是Spring mvc 的流程图

在旧版本中,DispatcherServlet之类的servlet一般在web.xml文件中配置;但是Spring 3.1引入了注解就无需再使用web.xml文件。

下面配置DispatcherServlet

 import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;  

 public class SpitterWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {  

     @Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{RootConfig.class};
} @Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{WebConfig.class};
} @Override
protected String[] getServletMappings() {
return new String[]{"/"};
} }

Spring 实战4学习笔记(转)的更多相关文章

  1. 《Spring实战》学习笔记-第五章:构建Spring web应用

    之前一直在看<Spring实战>第三版,看到第五章时发现很多东西已经过时被废弃了,于是现在开始读<Spring实战>第四版了,章节安排与之前不同了,里面应用的应该是最新的技术. ...

  2. spring cloud(学习笔记)高可用注册中心(Eureka)的实现(二)

    绪论 前几天我用一种方式实现了spring cloud的高可用,达到两个注册中心,详情见spring cloud(学习笔记)高可用注册中心(Eureka)的实现(一),今天我意外发现,注册中心可以无限 ...

  3. 《Angular4从入门到实战》学习笔记

    <Angular4从入门到实战>学习笔记 腾讯课堂:米斯特吴 视频讲座 二〇一九年二月十三日星期三14时14分 What Is Angular?(简介) 前端最流行的主流JavaScrip ...

  4. 《机器学习实战》学习笔记第十四章 —— 利用SVD简化数据

    相关博客: 吴恩达机器学习笔记(八) —— 降维与主成分分析法(PCA) <机器学习实战>学习笔记第十三章 —— 利用PCA来简化数据 奇异值分解(SVD)原理与在降维中的应用 机器学习( ...

  5. 《机器学习实战》学习笔记第九章 —— 决策树之CART算法

    相关博文: <机器学习实战>学习笔记第三章 —— 决策树 主要内容: 一.CART算法简介 二.分类树 三.回归树 四.构建回归树 五.回归树的剪枝 六.模型树 七.树回归与标准回归的比较 ...

  6. Spring源码学习笔记9——构造器注入及其循环依赖

    Spring源码学习笔记9--构造器注入及其循环依赖 一丶前言 前面我们分析了spring基于字段的和基于set方法注入的原理,但是没有分析第二常用的注入方式(构造器注入)(第一常用字段注入),并且在 ...

  7. Spring 源码学习笔记10——Spring AOP

    Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...

  8. Spring 源码学习笔记11——Spring事务

    Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...

  9. Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点

    Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...

随机推荐

  1. unittest---unittest数据驱动(ddt)

    在做测试的时候,有些地方无论是接口还是UI只是参数数据的输入不一样,操作过程是一样的.重复去写操作过程会增加代码量,我们可以通过参数化的方式解决这个问题,也叫做数据驱动,我们通过python做参数化的 ...

  2. 解决Python2中文ascii编码的方法

    在YiiChina签到的时候,经常会看到有人在说说里面发群主是最帅的,yii 是 PHP 最好的框架,没有之一,就想到使用一言,在每天签到的时候也发一句话 同时使用方糖将内容推送到微信,防止有什么不对 ...

  3. 新见Java数据类型_需了解

    LinkedList<T>.LinkedList.poll() 先给出结论:pop 与 poll 都是取出 LinkedList 的第一个元素,并将该元素删除,等效于:removeFirs ...

  4. Pytorch dataset自定义【直播】2019 年县域农业大脑AI挑战赛---数据准备(二),Dataset定义

    在我的torchvision库里介绍的博文(https://www.cnblogs.com/yjphhw/p/9773333.html)里说了对pytorch的dataset的定义方式. 本文相当于实 ...

  5. CSS 常用操作

    1.对齐 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <ti ...

  6. 题解 LG P2264

    这是题解P2264 先讲一下Trie,其实Trie也名前缀树,就是说:如果Trie中某串是某串的前缀,那么我们可以共用这个串也就是这样: 插入h.hk.jc,jcfa 那么,h节点会给h和hk共用,j ...

  7. Django3.0中向后不兼容的更改

    3.0中向后不兼容的更改 数据库后端API 本节描述了第三方数据库后端中可能需要的更改. 现在的第二个参数DatabaseIntrospection.get_geometry_type()是行描述,而 ...

  8. Java泛型与数组深入研究

    Java中的泛型与数组平时开发用的很多,除了偶尔遇到"NullPointerException"和"IndexOutOfBoundsException"一般也不 ...

  9. Eclipse创建一个动态maven项目详细步骤

    新建maven项目,new一个Dynamic Web Project 项目 输入完项目名直接finish 配maven,右键项目configure,选择Convert to Plug-in Proje ...

  10. Maven是什么,如何使用Maven

    一.简单的小问题? 1.1.假如你正在Eclipse下开发两个Java项目,姑且把它们称为A.B,其中A项目中的一些功能依赖于B项目中的某些类,那么如何维系这种依赖关系的呢? 很简单,这不就是跟我们之 ...