1.spring基本介绍

spring的出现给软件开发带来了春天,它极大程度的减轻了软件开发复杂的流程和难度。spring最核心的两个部分应该是ioc(控制反转)和aop(面向切面)。

ioc(控制反转):  应用程序本身不会实现对象的创建和维护,由外部容器负责创建和维护。不用实例化对象了,可以通过bean去配置。 反转的是获取对象的方式!以前通过new的方式去创建对象,现在通过getBean去容器中获取对象!

aop(面向切面): 底层思想是代理思想,它可以通过不修改源程序实现业务功能的拓展,比如说:在某个方法、某条语句前后打印日志消息等等

需要导入的jar包,我这里使用的是maven,所以导入依赖即可

<!--使用aop会用到的jar包-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>

<!--处理bean的jar-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>

<!--处理spring的上下文jar-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>

<!--spring的核心jar-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>

2.ioc注解与xml方式对比

xml方式

(1)创建一个学生类Student,里面包含id属性和name属性

(2)创建appicationContext.xml文件,放在resource文件夹下,并从官网粘贴如下的代码

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    #通过set的方式注入
    <bean id="student" class="com.org.entity.Student">
        <property name="id" value="12345"/>
    </bean>

</beans>

(3)创建一个测试类Test并运行结果, 出现12345代表成功实现ioc!!!  

注解方式:

(1)创建一个学生类Student,里面包含id属性和name属性,并在类的上方添加@Component注解 ,@Component注解的意思就是自动将该类注册到ioc容器里。 并在指定的属性通过@Value注解注入值

(2)创建一个配置类MyConfig,加上@Configuration注解就说明该类就是配置类了,但是@Configuration的底层仍是@Component。

@Bean注解就等同于xml中的 <bean>标签,Student类名就相当于<bean class="com.org.entity.Student"/>,方法名就相当于<bean id="student"/>, 整个MyConfig就等同于xml中的<beans></beans>标签。

(3)创建测试类,并在类上添加@componentScan("com.org")注解,该注解的作用是扫描组件到ioc容器,运行结果出现12345就代表你通过注解方式实现ioc控制反转成功啦!!!

@component注解衍生出几个注解

(1)@Repository  常用在dao层

(2)@service  常用在service层

(3)@controller  常用在controller层

3.aop注解与xml方式对比

aop面向切面的一些概念,官方说的太绕,我个人的理解是这样的:

(1)切面(aspect):实现业务功能的类

(2)通知(Advice): 业务功能类里面的具体方法

  

(3)目标(Target):  被通知对象

(4)代理(Proxy):  即代理类

(5)切入点(PointCut)   即在哪个地方执行

xml方式实现aop(面向切面):

需导入此依赖:

<!--使用aop织入需要导入的一个包-->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>

(1)创建Student学生类:

public class Student {
    int id;
    String name;

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public Student() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

(2) 创建service接口,里面包含着要实现增删改查功能:

public interface StudentService {
    public void add();
    public void delete();
    public void update();
    public void query();
}

(3)创建serviceImpl类,对service接口的方法具体实现

public class StudentServiceImpl implements StudentService {
    @Override
    public void add() {
        System.out.println("增加学生");
    }

    @Override
    public void delete() {
        System.out.println("删除学生");
    }

    @Override
    public void update() {
        System.out.println("修改学生");
    }

    @Override
    public void query() {
        System.out.println("查询学生");
    }
}

 (4)创建切面类QieMian,即在不修改源程序的情况下,你想实现的业务功能类 ,  before()和after()就是等价于通知,在源程序指定位置插入通知,实现源程序业务功能的拓展!!!

public class QieMian {
    public void before(){
        System.out.println("-----执行方法前---------");
    }
    public void after(){
        System.out.println("---------执行方法后------");
    }
}

(5)创建applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--注册Bean-->
    <bean id="student" class="com.org.entity.Student"/>
    <bean id="studentServiceImpl" class="com.org.serviceImpl.StudentServiceImpl"/>
    <bean id="qieMian" class="com.org.aspect.QieMian"/>

    <!--配置aop-->
    <aop:config>

        <!--配置切面-->
        <aop:aspect ref="qieMian">

            <!--切入点 excution(修饰词 返回值 类名 方法名 参数) ,excution代表要执行的位置-->
            <aop:pointcut id="point" expression="execution(* com.org.serviceImpl.StudentServiceImpl.*(..))"/>

            <!--通知-->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
</beans>

(6)创建测试类Test:

public class Test {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        //此处返回类型不是StudentServiceImpl类,而是StudentService接口,因为aop底层是代理,代理类要实现接口
        StudentService studentService= (StudentService) context.getBean("studentServiceImpl");
        studentService.add();
    }
}

 运行结果如下:

注解方式实现aop(面向切面)

(1)创建实体类Student,记得加上@Component注解,把此类注册到spring ioc容器中

@Component
public class Student {
    int id;
    String name;

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public Student() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

(2)创建service接口,里面包含着要实现增删改查功能:

public interface StudentService {
    public void add();
    public void delete();
    public void update();
    public void query();
}

(3)创建serviceImpl实现类,对service接口的方法具体实现,记得加上@Service注解,@Service@Component的衍生注解!!

@Service
public class StudentServiceImpl implements StudentService {
    @Override
    public void add() {
        System.out.println("增加学生");
    }

    @Override
    public void delete() {
        System.out.println("删除学生");
    }

    @Override
    public void update() {
        System.out.println("修改学生");
    }

    @Override
    public void query() {
        System.out.println("查询学生");
    }
}

(4)创建MyConfig配置类,相当于applicationContext.xml文件的功能,记得加上@Configuration注解,以及@EnableAspectAutoProxy  去开启aop注解支持!!

@Configuration
@EnableAspectJAutoProxy
public class MyConfig {

    @Bean
    public Student student(){
        return new Student();
    }
    @Bean
    public StudentServiceImpl studentServiceImpl(){
        return new StudentServiceImpl();
    }

    @Bean
    public QieMian qieMian(){
        return new QieMian();
    }

}

(5)定义切面类QieMian去拓展源代码业务功能,记得通过@Component去把切面类注册到spring ioc容器当中去,并通过@Aspect标注此类为切面类。@Before@After为通知,注解后面的参数为切入点,即指出在哪个包、哪个类、哪个方法使用通知!!

@Component
@Aspect
public class QieMian {

    @Before("execution(* com.org.serviceImpl.*.*(..))")
    public void before(){
        System.out.println("-----执行方法前---------");
    }

    @After("execution(* com.org.serviceImpl.*.*(..))")
    public void after(){
        System.out.println("---------执行方法后------");
    }
}

(6)创建测试类Test去测试结果

@ComponentScan("com.org")   //扫描组件所在的包
public class Test {
    public static void main(String[] args) {
        //此处返回类型不是StudentServiceImpl类,而是StudentService接口,因为aop底层是代理,代理类要实现接口
       ApplicationContext context=new AnnotationConfigApplicationContext(MyConfig.class);
       StudentService studentService=(StudentService) context.getBean("studentServiceImpl");
       studentService.add();
    }
}

 运行结果如下代表成功!!!

4.总结

(1) xml开发优势:

    ①spring的xml开发方式便于集中管理,与源代码解耦

    ②利于处理复杂的业务逻辑功能,例如后面整合mybatis时的多表联合查询

    ③xml是可扩展的,所以xml可以描述来自多种应用程序的数据

(2)xml开发劣势:

    ①开发速度比较慢

    ②配置的代码太多,不够轻巧简便,不利于查看

(3)注解开发优势:

    ①开发速度快

    ②代码利于查看且轻巧简便

    ③体现你高逼格,拉开那些只会xml开发人员的差距

    ④springboot基本上都是使用注解开发,因此采用注解开发便于springboot的学习与理解!!

(4)注解开发劣势:

    ①不利于代码维护,体现在它是分散式的元数据,与源代码耦合!!

    ②自己在注解中手误的时候,比如多敲一个*,少敲一个*,不易发现

    ③后面整合mybatis时,注解不方便多表联合查询!!

    ④当程序出现问题时,要通过修改源代码方式解决问题,这是开发的大忌!! 开发最好的情况就是能不动源代码就不动源代码,通过配置类或者面向切面或者数据库实现业务逻辑功能的扩展,这才是软件开发的最高境界

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐