Spring框架 --- 深入

1.Spring IOC

  IOC技术: 控制反转,也叫(依赖注入)

  控制反转:Bean的生命周期不受你控制,而是交给Spring容器管理。

  Spring框架如何利用IOC ?:
          实现了控制反转,Spring容器能帮我们实例化对象,但是并没有做到DI(依赖注入)。

  作用:
        (1) 构建Bean
        (2) Bean之间有依赖关系的话,可以自动帮我们注入
    优势:
        解耦:低耦合,实现面向接口的编程思想

2.Spring AOP

  动态代理设计模式
      原理和静态代理设计模式没有本质区别:
          被代理类、代理类、被代理和代理类是同一个接口
          代理类的创建过程有区别:
          (1)静态代理:
                  自己编写代理类,代理类自己实现接口
          (2)动态代理:
                  代理类不需要自己编写,他Proxy.newProxyinstance(xx)静态方法
                  在程序执行过程中,动态产生代理类
                  InvocationHandler:里边含有被代理类的引用

   AOP:面向切面的编程

  代理模式主要的作用:
          在业务代码不之情的情况下,切入额外的功能。
    原理:Spring框架具有IOC的功能,所以我们可以利用该功能配置业务Bean 。代理设计模式(动态)
        例如: AccountServiceImpl
        <bean id="AccountServiceImpl" class="service.AccountServiceImpl"></bean>
        然后,Spring框架利用动态代理设计模式创建一个AccountServiceImpl的动态代理对象
        然后就可以在AccountServiceImpl的业务方法的基础上增加相应的功能。
        那Spring把这种技术称为AOP面向切面的编程,其实就是在程序员不知情的情况下在其业务方法上切入额外的功能。

  使用 XML 配置实现具体的操作:
      (1)使用Spring的AOP功能,就需要引入jar  pom.xml
      (2)自己编写切面。很类似于InvocationHandler
          被代理接口   :  业务接口
          被代理类: 实现了被代理口,被代理类也叫业务实现类;
          例子:class CalFfabImpl implements ICalFab

代码示例:

  Maven项目

  pom.xml 添加的插件  

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.10</version>
        </dependency>       
 <!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.10</version>
        </dependency>
                
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>            

  添加资源配置文件 beans.xml

<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"
    xmlns:aop="http://www.springframework.org/schema/aop"
    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.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- Spring IOC --> 
   <bean id="calFab" class="day02.aop.CalFabImpl"></bean>
   <bean id="selfAspectRef" class="day02.aop.SelfAspect"></bean>
   
   <!-- Spring Aop 配置切面 -->
   <aop:config>
           <!-- 配置切面 -->
           <aop:aspect ref="selfAspectRef">
               <!-- 切点  在CalFabImpl类的任何方法上加通知 -->
               <aop:pointcut expression="execution(* day02.aop.CalFabImpl.*(..))" id="selfPointcut"/>
               <!-- 通知 -->
               <aop:before method="testBefore" pointcut-ref="selfPointcut"/>
               <aop:after method="testAfter" pointcut-ref="selfPointcut"/>
               <aop:around method="testAround" pointcut-ref="selfPointcut"/>
           </aop:aspect>
   </aop:config>
   
</beans>

  新建接口 ICalFab.java

 1 /**
 2  * 业务接口
 3  * @author 张泽
 4  */
 5 public interface ICalFab {
 6     
 7     int calFaByLoop(int n);
 8     int calFabByRecursion(int n); 
 9 
10 }

  新建类实现接口:

/**
 * 业务实现类:被代理类
 * @author 张泽
 */
class CalFabImpl implements ICalFab{
    @Override
    public int calFaByLoop(int n) {
        int n1=1,n2= 1,n3=0;
        for (int i = 3; i < n; i++) {
            n3=n1+n2;
            n1=n2;
            n2=n3;
        }
        return n3;
    }
    @Override
    public int calFabByRecursion(int n) {
        if(n==1||n==2) return 1;
        return calFabByRecursion(n-1)+calFabByRecursion(n-2);
        
    }
    
    
}

  新建类:SelfAspect.java

import org.aspectj.lang.ProceedingJoinPoint;

/**
 * 自定义功能性切面:利用xml配置实现。
 * @author 张泽
 *
 */
public class SelfAspect {
    //--通知:Before类型的Advice
    public void testBefore() {
        System.out.println("before do something...");
    }
    //--通知:after类型的通知
    public void testAfter() {
        System.out.println("after do Something...");
    }
    //-- 通知:Around环绕   通知方法的执行点
    public int testAround(ProceedingJoinPoint jp) {
        int result = 0;
        try {
            long start = System.currentTimeMillis();
            result = (int)jp.proceed();    //-- 执行业务方法
            long end = System.currentTimeMillis();
            System.out.println(end-start+"ms");
        } catch (Throwable e) {
            e.printStackTrace();
        }    
        return result;
    }
} 

  新建调用类:Invoker.java

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Invoker类
 * 功能切入更加灵活
 * @author 张泽
 *
 */
public class Invoker {
    public static void main(String[] args) {
        //-- 1. Spring容器
        ApplicationContext ctx =
                new ClassPathXmlApplicationContext("application.xml");
        //-- 2. 获取业务类
        ICalFab calFab= (ICalFab)ctx.getBean("calFab");
        //-- 3. 调用业务方法
        System.out.println(calFab.calFaByLoop(40));
        System.out.println(calFab.calFabByRecursion(40));
        System.out.println(calFab instanceof ICalFab);
        
    }
}

  使用 注解 配置实现具体的操作:

    (1) Config类来代替xml的配置
          @EnableAspectJAutoProxy //-- 启用SpringAop的功能
          //-- 启用Spring的IOC功能
          @Configuration
          @ComponentScan({"package1","package2"})
      (2)编写切面。

代码示例:

  新建接口 ICalFab.java 

/**
 * 业务接口
 * @author 张泽
 *
 */

public interface ICalFab {
    
    int calFaByLoop(int n);
    int calFabByRecursion(int n); 

}

  新建实现类 CalFabImpl.java

import org.springframework.stereotype.Component;

/**
 * 业务实现类:被代理类
 * @author 张泽
 */
@Component    //-- Spring IOC
class CalFabImpl implements ICalFab{
    @Override
    public int calFaByLoop(int n) {
        int n1=1,n2= 1,n3=0;
        for (int i = 3; i < n; i++) {
            n3=n1+n2;
            n1=n2;
            n2=n3;
        }
        return n3;
    }
    @Override
    public int calFabByRecursion(int n) {
        if(n==1||n==2) return 1;
        return calFabByRecursion(n-1)+calFabByRecursion(n-2);
        
    }
    
    
}

  新建配置类 AppConfig.java

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * 配置类
 * @author 张泽
 * 实现IOC功能
 * 
 */
@Configuration
@EnableAspectJAutoProxy //-- 启用SpringAop的功能
@ComponentScan("day.annocation")//-- 包名
public class AppConfig {
//    @Bean
//    public ICalFab calFabBean() {
//        return new CalFabImpl();
//    }
}

  新建类:SelfAspect.java

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * 利用标注自定义切面
 * @author 张泽
 *
 */
@Aspect
@Component
public class SelfAspect {
    
    //-- 1. 自定义切点,指定目标方法的位置
    @Pointcut("execution(* day02.annocation.CalFabImpl.*(..))")
    public void selfPointcut() {
        
    }
    //-- 2. 通知
    @Before("selfPointcut()")
    public void testBefore() {
        System.out.println("before do something...");
    }
    
    @After("selfPointcut()")
    public void testAfter() {
        System.out.println("After do something...");
    }
    @Around("selfPointcut()")
    public int testAround(ProceedingJoinPoint jp) {
        int result = 0;
        try {
            long start = System.currentTimeMillis();
            result = (int)jp.proceed();    //-- 执行业务方法
            long end = System.currentTimeMillis();
            System.out.println(end-start+"ms");
        } catch (Throwable e) {
            e.printStackTrace();
        }    
        return result;
    }
}

  新建类:Invoker.java

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Invoker {
    public static void main(String[] args) {
        //-- 1.构造Spring容器
        ApplicationContext ctx = 
                new AnnotationConfigApplicationContext(AppConfig.class);
        //-- 2.获取Beans
        ICalFab calFab =(ICalFab)ctx.getBean("calFabImpl");//-- 默认是类名首字母小写
        calFab.calFabByRecursion(40);
        
        //-- Web服务器启动的时候实例化一个Spring容器,在Web服务器关闭的时候关闭Spring容器
        //-- Servlet的监听
        //-- 容器关闭
        ((AnnotationConfigApplicationContext)ctx).close();
    }
}

3.Spring Test


     Spring 的测试框架建立在JUnit测试框架基础上的,它是对JUnit的再次封装。

使用:

  配置文件 pom.xml 引入插件

<!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12-beta-3</version>
            <scope>test</scope>
        </dependency>
        <!-- Spring Test -->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.7.RELEASE</version>
            <scope>test</scope>
        </dependency>

示例测试工程的代码:

/**
 * 业务接口
 * @author 张泽
 *
 */

public interface IUserService {
    void login();
}
import org.springframework.stereotype.Component;

/**
 * 业务实现类
 * @author 张泽
 *
 */
@Component
public class UserServiceImpl implements IUserService {

    @Override
    public void login() {
        System.out.println("login success");
        
    }

}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * Spring配置
 * @author 张泽
 *
 */
@Configuration
@ComponentScan("day03")
public class AppConfig {
    
    @Bean("hello")
    public String hello() {
        return "hello";
    }
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * 调用
 * @author 张泽
 *
 */
public class Invoker {
    public static void main(String[] args) {
        //-- Spring COntainer
        ApplicationContext ctx = 
                new AnnotationConfigApplicationContext(AppConfig.class);
        //-- 2.
        System.out.println(ctx.getBean("hello"));
    }
}

JUnit测试代码:

/**
 * 1. 先利用JUnit做单元测试
 * @author 张泽
 *
 */

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestDemo {
    private ApplicationContext ctx;
    
    @Before
    public void before() {
        ctx = new AnnotationConfigApplicationContext(AppConfig.class);    
    }
    
    @Test
    public void test() {
        System.out.println(ctx.getBean("hello"));
    }
    
    
}
利用Spring test 框架测试:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * 2. 利用Spring test 框架
 * 
 * @RunWith: 实例化Spring容器
 * @ContextConfiguration: 指定Spring容器需要的配置类
 * 以后你会很少看到Spring容器了
 * 
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes= {AppConfig.class})
public class TestSpringDemo {
    @Autowired
    private String hi;
    @Autowired
    private IUserService userService;
    
    @Test
    public void test() {
        System.out.println(hi);
    }
    @Test
    public void test1() {
        userService.login();
    }
}

该项目的配置文件:pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.uek.course</groupId>
    <artifactId>spring-app</artifactId>
    <version>0.0.1</version>
    <packaging>war</packaging>

    <!-- 2. 项目属性配置 -->
    <properties>
        <!-- 项目编码使用UTF-8 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!-- 忽略掉web.xml文件 ,因为我们使用servlet3.0开发web项目 -->
        <failOnMissingWebXml>false</failOnMissingWebXml>
        <spring.version>5.1.7.RELEASE</spring.version>
    </properties>
    <!-- 3. 配置项目所需要的第三方jar 包 -->
    <dependencies>
        <!-- servlet api -->
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <!-- MySQL数据库连接池 -->
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.48</version>
        </dependency>

        <!-- Druid -->
        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.20</version>
        </dependency>
        <!-- 单元测试 -->
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12-beta-3</version>
            <scope>test</scope>
        </dependency>
        <!-- Spring Test -->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>
        
        
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        
        
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.10</version>
        </dependency>
        
        
        <!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.10</version>
        </dependency>
                
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        
    
    
    </dependencies>



    <!-- 配置构建插件 -->
    <build>
        <plugins>
            <plugin>
                <!-- 编译插件 -->
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <!-- Tomcat 插件 -->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <port>8080</port>
                    <path>/airsys</path>
                    <!-- 实现热部署,不需要每次修改代码后都重新启动Tomcat -->
                    <contextReloadable>true</contextReloadable>
                </configuration>
            </plugin>


        </plugins>
    </build>
</project>

猜你喜欢

转载自www.cnblogs.com/zhangze-lifetime/p/11768566.html