从毕业到现在我一直从事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();
    }
}

使用比较简单,和前文基本一致,我们来看看运行结果:

本案例下载地址:

本案例GitHub地址

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

Spring基础配置的更多相关文章

  1. 01—Spring基础配置IOC

  2. SpringMVC基础配置(通过注解配置,非xml配置)

    SpringMVC是什么,有多火,我这里就不再啰嗦了,SpringMVC比Struts2好用太多,我在学校的时候私下里两种都接触过,对比之后果断选择了SpringMVC,后来在做Android应用开发 ...

  3. Spring Boot实战(1) Spring基础

    1. Spring基础配置 Spring框架本身有四大原则: 1) 使用POJO进行轻量级和最小侵入式开发 2) 通过依赖注入和基于接口编程实现松耦合 3) 通过AOP和默认习惯进行声明式编程 4) ...

  4. Spring Boot学习第一部分(Spring 4.x)第一章(Spring 基础)

    1.spring概述 1.1.spring的简史 第一阶段:XML配置spring 1.x时代, 第二阶段:注解配置spring 2.x时代, @Controller @Service @Compon ...

  5. 转 RabbitMQ 基础概念及 Spring 的配置和使用 推荐好文 举例讲解

    从不知道到了解—RabbitMQ 基础概念及 Spring 的配置和使用 原理同上 请求地址:http://localhost:8080/home?type=3&routing_key=myO ...

  6. Spring Boot 基础配置

    之前简单接触了一些Spring Boot ,并且写了一个简单的 Demo .本文就来简单学习一下 Spring Boot 的基础配置. 一.Spring Boot 项目入口 上文中有写到,Spring ...

  7. Java进阶知识15 Spring的基础配置详解

    1.SSH各个的职责 Struts2:是web框架(管理jsp.action.actionform等).Hibernate:是ORM框架,处于持久层.Spring:是一个容器框架,用于配置bean,并 ...

  8. Spring基础——在Spring Config 文件中配置 Bean

    一.基于 XML 的 Bean 的配置——通过全类名(反射) <bean <!-- id: bean 的名称在IOC容器内必须是唯一的若没有指定,则自动的将全限定类名作为 改 bean 的 ...

  9. Spring基础篇——通过Java注解和XML配置装配bean

    自动化装配的确有很大的便利性,但是却并不能适用在所有的应用场景,比如需要装配的组件类不是由自己的应用程序维护,而是引用了第三方的类库,这个时候自动装配便无法实现,Spring对此也提供了相应的解决方案 ...

随机推荐

  1. java中匿名内部类的应用

    如果某一个类实现了接口,而且仅仅在程序代码中使用了一次,那么就没必要单独定义该方法,可以通过接口来定义匿名内部类 interface Message{ public void print(); } p ...

  2. [HNOI2016]序列

    题目描述 给定长度为n的序列:a1,a2,...,an,记为a[1:n].类似地,a[l:r](1<=l<=r<=N)是指序 列:al,al+1,...,ar-1,ar.若1< ...

  3. 洛谷P1397 [NOI2013]矩阵游戏

    矩阵快速幂+费马小定理 矩阵也是可以跑费马小定理的,但是要注意这个: (图是盗来的QAQ) 就是说如果矩阵a[i][i]都是相等的,那么就是mod p 而不是mod p-1了 #include< ...

  4. ●BZOJ 4176 Lucas的数论

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4176 题解: 莫比乌斯反演,杜教筛 首先有这么一个结论: 令d(n)表示n的约数的个数(就是 ...

  5. 洛谷P2042 [NOI2005]维护数列

    #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #in ...

  6. 51 nod 1515 明辨是非(并查集合并)

    1515 明辨是非题目来源: 原创基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 给n组操作,每组操作形式为x y p. 当p为1时,如果第x变量和第y个变量可以 ...

  7. 【Luogu P2709 小B的询问】莫队

    题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重 ...

  8. HDU 4501

    超市里有n件他想要的商品.小明顺便对这n件商品打了分,表示商品的实际价值.小明发现身上带了v1的人民币,会员卡里面有v2的积分,而且他能免费拿k件.他想知道他最多能买多大价值的商品. 由于小明想要的商 ...

  9. 例10-2 uva12169(扩展欧几里得)

    题意:已知xi=(a*xi-1+b) mod 10001,且告诉你x1,x3.........x2*t-1,让你求出其偶数列 思路: 枚举a,然后通过x1,x3求出b,再验证是否合适 1.设a, b, ...

  10. day5 liaoxuefeng---实战篇