Spring基础配置
从毕业到现在我一直从事Android开发,但是对JavaEE一直念念不忘,毕业校招的时候,一个礼拜拿了三个offer,岗位分别是Android、JavaEE和JavaSE,后来觉得Android比较简单,而且在当时也比较受欢迎,于是阴差阳错跳到了这个坑中,从此心里也一直有个结,很多时候都想重新拾起JavaEE,却由于工作原因难以实现,age也在慢慢变大。 上上个月CSDN专家奖励,我和梦鸽美女要了一本《JavaEE开发的颠覆者 Spring Boot实战》这本书,打算认真复习一下JavaEE,书到手之后一直束之高阁,现在到了年底,手头上的工作不是特别繁忙,于是决定年前花点时间重温一下JavaEE。 OK,以上算是缘起吧。 JavaEE的复习我觉得就顺着这本书的思路来复习,jsp、Servlet那些过于简单的就不再赘述,当然我由于长时间未从事专业的JavaEE开发,文中若有遗漏讹误欢迎专业人士拍砖。 OK,今天我想先来回顾下Spring基础配置。
Spring 配置问题
Spring的配置常见的有三种方式:
1.xml文件配置 2.注解配置 3.Java配置
一般来说,我们在选择配置方式的时候,应用的基础配置选择xml的方式来完成,业务配置使用注解来完成。
Spring框架本身有四大原则:
1.使用POJO进行轻量级和最小侵入式开发 2.通过依赖注入和基于接口编程实现松耦合 3.通过AOP和默认习惯进行声明式编程 4.使用AOP和模板减少模式化的代码
Spring中所有功能的设计和实现都是基于这四大原则的。这里关于AOP很多初学的小伙伴都不太理解,这里大家可以参考这篇回答什么是面向切面编程AOP?。懒得打开链接的直接看下图:
Spring常见注解
声明Bean的注解:
1.@Component组件,没有明确角色 2.@Service组件(使用在service层) 3.@Repository组件(使用在dao层) 4.@Controller组件(使用SpringMVC时使用) 注入Bean的注解 1.@Autowired(Spring提供的注解) 2.@Inject(JSR-330提供的注解,使用时要导入相应的jar包) 3.@Resource(JSR-250提供的注解)
注入Bean的这三个注解既可以直接用在属性上,也可以用在该属性的set方法上,一般建议使用前者,简洁高效。
OK,接下来我们来通过三个案例来看看三种不同的配置方式。
依赖注入
先来看第一种配置方式。
1.创建一个Maven项目,添加Spring依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
</dependencies>
2.编写功能类Bean
@Service
public class FunctionService {
public String sayHello(String word) {
return "你好" + word + "!";
}
}
@Service注解表示这个类属于Service层,并且是由Spring管理的一个类。当然这里也可以选用@Repository、@Component、@Controller注解,效果相同。实际应用中根据相关类所处的位置选用合适的注解。 3.使用功能类Bean
@Service
public class UseFunctionService {
@Autowired
FunctionService functionService;
public String sayHello(String word) {
return functionService.sayHello(word);
}
}
@Service注解含义不再多说,@Autowired注解表示将FunctionService的实体Bean注入到UseFunctionService中,这里也可以使用上文提到的@Inject或者@Resource,效果相同。 4.配置类
@Configuration
@ComponentScan("org.sang")
public class MyConfig {
}
@Configuration表示该类是一个配置类,@ComponentScan表示扫描org.sang
包下所有使用了@Service、@Controller、@Component、@Repository注解的类,并将之注册为Bean。
5.使用
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
UseFunctionService bean = context.getBean(UseFunctionService.class);
System.out.println(bean.sayHello("sang"));
context.close();
}
}
这里我们使用AnnotationConfigApplicationContext来作为Spring容器,它的参数就是我们之前创建的配置类,然后通过getBean方法来获取类的Bean,最后调用Bean中的方法。 输出结果如下:
源码地址:
本项目GitHub地址
Java配置
OK,上文我们说了依赖注入,接下来来看看Java配置,Java配置是Spring4.x推荐的配置方式,也算是一种比较潮的方式,在使用的过程中建议全局配置使用Java配置(数据库配置等),业务配置使用注解配置,不仅在JavaEE中,在Android开发中也有一个依赖注入框架Dagger2,也使用了类似的方式。OK,我们来看看Java配置的使用方式:
1.编写功能类Bean
public class FunctionService {
public String sayHello(String word) {
return "你好 " + word + " !";
}
}
小伙伴们注意功能类Bean并没有使用@Service等注解。 2.使用功能类Bean ``` public class UseFunctionService { FunctionService functionService;
public void setFunctionService(FunctionService functionService) {
this.functionService = functionService;
}
public String sayHello(String word) {
return functionService.sayHello(word);
}
}
小伙伴们注意,这里的类也没有使用@Service注解,同时FunctionService属性也没有使用@Autowired注解。
> 3.编写配置文件
@Configuration public class MyConfig { @Bean public FunctionService functionService() { return new FunctionService(); }
@Bean
public UseFunctionService useFunctionService(FunctionService functionService) {
UseFunctionService useFunctionService = new UseFunctionService();
useFunctionService.setFunctionService(functionService);
return useFunctionService;
}
}
首先,@Configuration注解表示这是一个配置文件,同时这里没有使用包扫描注解,因为所有需要实例化的Bean都在类中有对应的方法去实现。这里我们使用了@Bean注解,该注解表示当前方法的返回值是一个Bean,Bean的名称就是方法名。在获取UseFunctionService的实例时,需要一个FunctionService的参数,在实例化UseFunctionService的时候,系统会自动查找它需要的Bean并作为参数传入,有木有觉得方便又熟悉呢?Android中的Dagger2不就是这样吗!
> 4.使用
public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); UseFunctionService bean = context.getBean(UseFunctionService.class); System.out.println(bean.sayHello(“sang”)); context.close(); } }
使用比较简单,和前文基本一致,我们来看看运行结果:
![这里写图片描述](http://img.blog.csdn.net/20161213111845355?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMjcwMjU0Nw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
本案例下载地址:
[本案例GitHub地址](https://github.com/lenve/JavaEETest/tree/master/Test5)
### AOP
OK,看了前面两种不同配置方式之后,接下来我们再来看看AOP,面向切面编程,关于面向切面编程如果小伙伴有不理解的可以回顾上文给出的知乎上的答案。OK,那我们就来看看怎么样来玩一玩AOP。
>1.添加Spring AOP支持及AspectJ依赖
和前文不同,使用AOP需要我们添加Spring框架对AOP的支持,同时需要添加AspectJ依赖,添加方式如下:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
<!--AOP支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
<!--aspectj支持-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
</dependencies>
>2.编写拦截规则的注解
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Action { String name(); }
这就是一个普通的注解,@Target一行表示该注解将作用在方法上,@Retention一行表示该注解将一直保存到运行时,@Documented表示该注解将保存在javadoc中。
>3.使用注解被拦截
@Service public class AnnotationService { @Action(name = “add-1”) public void add1() { System.out.println(“add-1”); }
public void add2() {
System.out.println("add-2");
}
@Action(name = "add-3")
public void add3() {
System.out.println("add-3");
}
}
>4.使用方法规则被拦截
@Service public class MethodService { public void add() { System.out.println(“method-add()”); } }
>5.编写切面
@Aspect @Component public class LogAspect { @Pointcut(“@annotation(org.sang.Action)”) public void annotationPointCut() {
}
//after表示先执行方法,后拦截,before表示先拦截,后执行方法
// @Before(“annotationPointCut()”) @After(“annotationPointCut()”) public void after(JoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); Action action = method.getAnnotation(Action.class); System.out.println(“注解式拦截:”+action.name()); }
/**
* 第一个星号表示返回类型,×表示所有类型,注意第一个星号和包名之间有空格
* 后面的星号表示任意字符
* 两个点表示任意个参数
*
* 参考 http://www.cnblogs.com/yansum/p/5898412.html
* @param joinPoint
*/
@Before("execution(* org.sang.MethodService.*(..))")
public void before(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
System.out.println("方法规则式拦截:"+method.getName());
}
}
首先这里我们通过@AspectJ注解声明该类是一个切面,然后添加的@Component注解让这个切面成为Spring容器管理的Bean。@PointCut声明的是一个切点,这个切点是所有使用了@Action注解的方法。然后我们通过@After声明一个建言,使用@PointCut定义的切点。当然我们也可以通过方法规则来设置切点,这个详见execution。
>6.配置类
@Configuration @ComponentScan(“org.sang”) @EnableAspectJAutoProxy public class MyConfig {
}
这里的配置类就比较简单了,@EnableAspectJAutoProxy表示开启Spring对AspectJ代理的支持。
>7.运行
public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); AnnotationService annotationService = context.getBean(AnnotationService.class); annotationService.add1(); annotationService.add2(); annotationService.add3(); MethodService methodService = context.getBean(MethodService.class); methodService.add(); context.close(); } } ``` 运行很简单,我们来看看运行结果:
本案例源码: 本案例GitHub地址
以上。
参考资料:
1.《JavaEE开发的颠覆者 Spring Boot实战》第一章 2.https://www.zhihu.com/question/24863332 3.http://www.cnblogs.com/yansum/p/5898412.html
- Laravel-博客实战+踩坑laravel-blog最终的效果踩的坑
- React项目配置3(如何管理项目API接口)
- React第三方组件3(状态管理之Flux的使用④TodoList下)
- React第三方组件3(状态管理之Flux的使用③TodoList中)
- Vue实现百度下拉提示搜索一、前期准备二、代码实现三、实现效果
- React第三方组件3(状态管理之Flux的使用②TodoList上)
- ggplot2玫瑰图案例——星巴克门店分布图
- React第三方组件3(状态管理之Flux的使用①简单使用)
- 用ggplot2画了一个我也叫不上名的炫酷图表
- React技巧8(不再手动绑定this,跟.bind(this)说88)
- 美美的商务范儿——ggplot2蝴蝶图
- 机器学习(三)使用Python和R语言从头开始理解和编写神经网络介绍目录神经网络背后的直观知识多层感知器及其基础知识什么是激活函数?前向传播,反向传播和训练次数(epochs)多层感知器全批量梯度下降
- React第三方组件2(状态管理之Refast的使用⑤LogicRender使用)
- 左右用R右手Python9——字符串合并与拆分
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 使用prepareStatement连接数据库实现增、删、改、查
- 插入排序图解与代码示例
- 初步使用Druid连接池+代码示例:对图书进行增删改查
- 创建Servlet的几种方式+web.xml中关于servlet的一些配置+浏览器、服务器交互Postman测试
- 二分法查找介绍+代码
- API文档的自动生成
- cookie创建的三个参数(有效期+有效路径+httponly)
- interface概念与代码示例,常量接口和标记接口,与abstract的区别
- Java8异步编程就是拽
- 如果try{}里面有一个return语句,那么紧跟着这个try后的finally{}里面的代码会不会执行?
- 二叉查找树代码java+运行结果
- 全选
- 在控制台,递归显示文件夹下所有文件目录代码+ 运行结果
- 使用bootstrap时下拉菜单失效问题解决
- 使用文件字节输出流FileOutputStream写入文件