从毕业到现在我一直从事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. [LeetCode] Count Binary Substrings 统计二进制子字符串

    Give a string s, count the number of non-empty (contiguous) substrings that have the same number of ...

  2. animation-timing-function的steps详解

    W3C里的定义: animation-timing-function 规定动画的速度曲线. 这个属性有很多取值, linear: 线性过渡.等同于贝塞尔曲线(0.0, 0.0, 1.0, 1.0) e ...

  3. [测试题]wows

    Description 山山最近在玩一款游戏叫战舰世界(steam 游戏太少了),他被大舰巨炮的魅力折服,于是山山开了一局游戏,这次发现目标是一艘战列舰新墨西哥级,舰桥很高,原本应该打在目标身后的圆形 ...

  4. [ZJOI2013]丽洁体

    题目描述 平时的练习和考试中,我们经常会碰上这样的题:命题人给出一个例句,要我们类比着写句子.这种往往被称为仿写的题,不单单出现在小学生的考试中,也有时会出现在中考中.许多同学都喜欢做这种题,因为较其 ...

  5. bzoj 2004: [Hnoi2010]Bus 公交线路

    Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距 离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决 ...

  6. bzoj2338[HNOI2011]数矩形 计算几何

    2338: [HNOI2011]数矩形 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1535  Solved: 693[Submit][Status ...

  7. bzoj1499[NOI2005]瑰丽华尔兹 单调队列优化dp

    1499: [NOI2005]瑰丽华尔兹 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 1802  Solved: 1097[Submit][Status ...

  8. SpringCloud学习之DiscoveryClient探究

    当我们使用@DiscoveryClient注解的时候,会不会有如下疑问:它为什么会进行注册服务的操作,它不是应该用作服务发现的吗?下面我们就来深入的来探究一下其源码. 一.Springframewor ...

  9. Django中数据查询(万能下换线,聚合,F,Q)

    数据查询中万能的下划线基本用法: __contains: 包含 __icontains: 包含(忽略大小写) __startswith: 以什么开头 __istartswith: 以什么开头(忽略大小 ...

  10. tensorflow deepmath:基于深度学习的自动化数学定理证明

    Deepmath Deepmath项目旨在改进使用深度学习和其他机器学习技术的自动化定理证明. Deepmath是Google研究与几所大学之间的合作. 免责声明: 该存储库中的源代码不是Google ...