(启动该项目需要连接mysql和redis)
基于Maven构建的SpringBoot项目,包括Spring框架的学习
Spring框架结构图
1)核心容器(Core Container) Spring-Core:核心工具类,Spring其他模块大量使用Spring-Core。 Spring-Beans:Spring定义Bean的支持。 Spring-Context: 运行时Spring容器。 Spring-Context-Support:Spring容器对第三方包的集成支持。 Spring-Expression:使用表达式语音在运行时查询和操作对象。
2)AOP Spring-AOP:基于代理的AOP支持。 Spring-Aspects:基于AspectJ的AOP支持。
3)消息(Messaging) Spring-Messaging:对消息架构和协议的支持。
4)Web Spring-Web:提供基础的Web集成功能,在Web项目中提供Spring容器。 Spring-WebMvc:提供基于Servlet的SpringMVC。 Spring-WebSocket:提供WebScoket功能。 Spring-WebMvc-Portlet:提供Portlet环境支持。
5)数据访问/集成(Data Access/Integration) Spring-JDBC:提供以JDBC访问数据库的支持。 Spring-TX:提供编程式事务和声明式事务的支持。 Spring-ORM:提供对对象/关系映射技术的支持。 Spring-OXM:提供对对象/xml映射技术的支持。(配置的映射) Spring-JMS:提供对JMS的支持。(java消息服务)
声明Bean的注解: @Component组件,没有明确的角色。 @Service在业务逻辑层(Service层)使用。 @Repository在数据访问层(dao层)使用。 @Controller在表现层(MVC--->SpringMVC)使用。
SpringIOC
Spring 控制反转(Spring-IOC): 具体实现是利用Spring依赖注入(SpringDI), 依赖注入是值容器负责创建对象和维护对象间的依赖关系,而不是通过对象本身辅助自己创建对象和解决自己的依赖。依赖注入的目的是为了解耦。 可以使用注解方式 和JavaConfig方式配置DI的Bean。 详细配置方式 请见:https://git.oschina.net/os_val/SpringBootDemo.git 其中的Spring DI包。
Spring-AOP
AOP:面向切面编程,相当于OOP的面向对象编程。 Spring的AOP目的是为了解耦,AOP可以使一组类共享相同的行为。 AOP它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于可操作性和可维护性。 使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
AOP核心概念 1、横切关注点 对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点 2、切面(aspect) 类是对物体特征的抽象,切面就是对横切关注点的抽象 3、连接点(joinpoint) 被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器 4、切入点(pointcut) 对连接点进行拦截的定义 5、通知(advice) 所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类 6、目标对象 代理的目标对象 7、织入(weave) 将切面应用到目标对象并导致代理对象创建的过程 8、引入(introduction) 在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
Spring对AOP的支持 Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它bean实例作为目标,这种关系可由IOC容器的依赖注入提供。Spring创建代理的规则为: 1、默认使用Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了 2、当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB AOP编程其实是很简单的事情,纵观AOP编程,程序员只需要参与三个部分: 1、定义普通业务组件 2、定义切入点,一个切入点可能横切多个业务组件 3、定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作 所以进行AOP编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP框架将自动生成AOP代理,即:代理对象的方法=增强处理+被代理对象的方法。
Spring支持AspectJ的注解式切面编程。 (1)使用@Aspect声明是一个切面。 (2)使用@After、@Before、@Around定义建言(advice),可直接将拦截规则(切点)作为参数。 (3)其中@After、@Before、@Around参数的拦截规则为切点(PointCut),为了使切点复用,可使用@PointCut专门定义拦截规则,然后在@After、@Before、@Around的参数中调用。 (4)其中符合条件的每一个被拦截处为连接点(JoinPoint)。 其中: @Before是在所拦截方法执行之前执行一段逻辑。 @After 是在所拦截方法执行之后执行一段逻辑。 @Around是可以同时在所拦截方法的前后执行一段逻辑。
详细配置方式 见:https://git.oschina.net/os_val/SpringBootDemo.git 其中的Spring AOP包下。
Bean的Scope Scope描述的是Spring容器如何新建bean的实例,Scope有以下几种,通过@Scope注解实现。 (1)Singleton(单例):一个Spring容器中只有一个bean的实例,此为Spring的默认配置,全容器共享一个实例。 (2)Prototype(原型):每次调用新建一个bean实例。 (3)Reqeuest:web项目中,给每一个http request新建一个bean实例。 (4)Session:web项目中,给每一个http session新建一个bean实例。 (5)GlobalSession:这个只在portal应用中有,给每一个global http session新建一个bean实例。 详细见:https://git.oschina.net/os_val/SpringBootDemo.git 其中的Spring Bean包下。
Spring EL 和 资源调用
SpringEL 表达式相当于JSTL。Spring调用各种资源可以使用Spring 表达式语音实现资源的注入。 注解@Value的参数中可以使用表达式语言,可注入包括普通字符、操作系统属性、表达式运算结果、其他bean属性、文件内容、网址内容、属性文件等。
package com.spring.EL;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
* Created by zsq on 16/12/18.
*/
@Service
public class DemoService {
/**
* 注入普通字符
*/
@Value(value = "其他类的属性")
private String another;
public String getAnother() {
return another;
}
public void setAnother(String another) {
this.another = another;
}
}
package com.spring.EL;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import java.io.IOException;
/**
* Created by zsq on 16/12/18.
* 其中test.properties 配置文件和test.txt 文本文件是放在 idea中的resources 目录下
*/
@Configuration
@ComponentScan(value = "com.spring.EL")
@PropertySource(value = "test.properties")
public class ELConfig {
/**
* 注入普通字符
*/
@Value("this is java")
private String normal;
/**
* 注入操作系统属性
*/
@Value("#{systemProperties['os.name']}")
private String osName;
/**
* 注入表达式结果
*/
@Value("#{ T(java.lang.Math).random()*100.0}")
private double randomNumber;
/**
* 注入其他bean属性
*/
@Value("#{demoService.another}")
private String fromAnother;
/**
* 注入文件资源
*/
@Value("test.txt")
private Resource textFile;
/**
* 注入网址资源
*/
@Value("http://www.baidu.com")
private Resource testURL;
/**
* 注入配置文件 此处使用${}
*/
@Value("${book.name}")
private String bookName;
@Autowired
private Environment environment;
/**
* 注入配置文件则需要@PropertySource 指定文件地址
* 若使用@Value 注入还需要配置一个PropertySourcesPlaceholderConfigurer的bean
* 注入的Properties 可以从Environment中获得
* @return
*/
@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfig() {
return new PropertySourcesPlaceholderConfigurer();
}
public void outputResource() throws IOException {
System.out.println(normal);
System.out.println(osName);
System.out.println(randomNumber);
System.out.println(fromAnother);
System.out.println(IOUtils.toString(textFile.getInputStream()));
System.out.println(IOUtils.toString(testURL.getInputStream()));
System.out.println(bookName);
System.out.println(environment.getProperty("book.author"));
}
}
public class ELMain {
public static void main(String[] args) throws IOException {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ELConfig.class);
ELConfig elConfig = context.getBean(ELConfig.class);
elConfig.outputResource();
context.close();
}
}
Profile profile为在不同环境下使用不同的配置提供了支持(开发和生成环境)。使用@Profile注解。
package com.spring.Profile;
/**
* Created by zsq on 16/12/18.
*/
public class DemoBean {
private String content;
public DemoBean(String content) {
this.content = content;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
package com.spring.Profile;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
/**
* Created by zsq on 16/12/18.
*/
@Configuration
public class ProfileConfig {
/**
* 实例化 devDemoBean
* @return
*/
@Bean
@Profile("dev")
public DemoBean devDemoBean() {
return new DemoBean("from development profile");
}
/**
* 实例化 prodDemoBean
* @return
*/
@Bean
@Profile("prod")
public DemoBean prodDemoBean() {
return new DemoBean("from production profile");
}
}
package com.spring.Profile;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.io.IOException;
/**
* Created by zsq on 16/12/18.
*/
public class ProfileDemoMain {
public static void main(String[] args) throws IOException {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles("prod");
context.register(ProfileConfig.class);
context.refresh();
DemoBean demoBean = context.getBean(DemoBean.class);
System.out.println(demoBean.getContent()); //from production profile
context.close();
}
}
事件(Application Event) Spring的事件(Application Event)为bean与bean之间的消息通信提供了支持。当一个bean处理完任务,希望另一个bean知道并作出相应的处理。这时要让另一个bean监听当前bean所发送的事件。 Spring的事件流程: (1)自定义事件,集成(继承)Application Event 类。 (2)定义事件监听器,实现ApplicationListener 接口 并实现onApplicationEvent(Event event) 方法。 (3)使用容器发布事件。
package com.spring.Event;
import org.springframework.context.ApplicationEvent;
/**
* Created by zsq on 16/12/18.
* 自定义事件
*/
public class DemoEvent extends ApplicationEvent{
private String msg;
public DemoEvent(Object source, String msg) {
super(source);
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
package com.spring.Event;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* Created by zsq on 16/12/18.
* 事件监听
* 实现ApplicationListener 并指定监听的类型DemoEvent
*/
@Component
public class DemoListener implements ApplicationListener<DemoEvent>{
/**
* 对消息进行接收处理
* @param demoEvent
*/
@Override
public void onApplicationEvent(DemoEvent demoEvent) {
String content = demoEvent.getMsg();
System.out.println("demoListener接收到demoPublisher的信息:"+content);
}
}
package com.spring.Event;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
/**
* Created by zsq on 16/12/18.
* 消息发布类
*/
@Component
public class DemoPublisher {
@Autowired
private ApplicationContext applicationContext;
public void publish(String msg) {
applicationContext.publishEvent(new DemoEvent(this, msg));
}
}
package com.spring.Event;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* Created by zsq on 16/12/18.
*/
@Configuration
@ComponentScan(value = "com.spring.Event")
public class EventConfig {
}
package com.spring.Event;
import com.spring.Profile.DemoBean;
import com.spring.Profile.ProfileConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.io.IOException;
/**
* Created by zsq on 16/12/18.
*/
public class EventDemoMain {
public static void main(String[] args) throws IOException {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(EventConfig.class);
DemoPublisher demoPublisher = context.getBean(DemoPublisher.class);
demoPublisher.publish("this is application event");
//demoListener接收到demoPublisher的信息:this is application event
context.close();
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。