Spring的核心IOC和AOP

IOC-控制反转

用最简单的话说就是IOC就是控制反转。控制就是对对象的创建和销毁的控制。反转就是由原来我们手动创建对象反转到由IOC容器提供对象

控制: 对象的创建对象的销毁
反转: 将创建对象的工作交给IOC容器

我用三种创建对象的方式去展示IOC的核心工厂模式+反射

普通创建对象方式

普通创建对象的方式就是直接new 这个对象。然后调用对象的方法。但是这种的方式耦合度太高。牵一发动全身

    /**
     * 测试调用用户对象的test方法
     * 普通创建对象
     */
    public static void main(String[] args) {
        // 普通对象创建
        User user = new User();
        // 调用测试类的方法
        user.testCs();
    }
    /**
     * 提供方法
     */
    public void testCs(){
        System.out.println("调用成功。。。。。。我是用户类");
    }

工厂创建对象方式

工厂模式创建对象相对的实现了消弱耦合。但是消弱的只是调用方和被调用方的耦合。实际上还是存在耦合就是工厂和被调用方

    /**
     * 将创建对象的工作交给工厂创建
     * @return
     */
    public static User findUser(){
        return new User();
    }
    /**
     * 测试调用用户对象的test方法
     * 工厂创建对象
     */
    public static void main(String[] args) {
        // 工厂创建对象
        User user = TestGc.findUser();
        // 调用测试类的方法
        user.testCs();
    }

工厂模式+反射方式创建对象(核心)

核心就是可以通过反射去根据类的路径 去生成对象。这个路径可以设置在xml中然后读取xml中的属性值 下次当你的类路径修改了。我只需要改xml一个地方就解决了所有的地方

    /**
     * 将创建对象的工作交给工厂创建
     * @return
     */
    public static User findUser(){

        // user类的路径 类的全限定名
        // 在配置文件中设置 然后反射加载获取属性值
        String luji = "com.macro.mall.user.User";
        try {
            // 加载指定的类 返回class对象的引用
            Class user = Class.forName(luji);
            System.out.println("创建成功!!!");
            // 创建一个对象实例然后返回
            return (User) user.newInstance();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 测试调用用户对象的test方法
     * 工厂创建对象
     */
    public static void main(String[] args) {
        // 工厂创建对象
        User user = TestGc.findUser();
        // 调用测试类的方法
        user.testCs();
    }

Spring的核心IOC和AOP_第1张图片

IOC核心

IOC实现容器的两种方式BeanFactoryApplicationContext
什么是BeanFactory
BeanFactory:是IOC的顶级接口 它定义了一些功能 但是功能比较简单 一般不面向程序使用
特点:只有在第一次调用bean创建对象的时候 他才会对bean实例化 俗称懒汉式
什么是ApplicationContext
ApplicationContext:是根据BeanFactory衍生出的一个子接口 它扩展了BeanFactory的一些功能 一般面向程序使用
特点:当程序启动的时候就会生成所有bean的实例化 我们只需要使用就可以了 实例的工作都在项目启动的时候做 俗称饿汉式

ApplicationContext有两个实现类FileSystemXmlApplicationContextClassPathXmlApplicationContext
这两个都是去读配置文件。只是参数有一些区别

  • FileSystemXmlApplicationContext:如果你的配置文件是在C盘本地路径中。那么参数就需要使用全路径
  • ClassPathXmlApplicationContext:如果你的配置文件是在项目中的src下。那么参数就只给配置文件名称即可

xml工作流程
刚才说了三种的创建方式。普通->工厂->工厂+反射 做这些的目的就是为了更大一步的实现消弱耦合度 IOC其实就是一个容器 而容器里边装的就是你交给IOC需要创建对象的类 什么时候用什么时候从里边拿就可以了。不需要你手动的创建 下边看下如何拿对象

在src下创建.xml文件来以配置的方式创建对象
.xml 标签


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    
    <bean id="user" class="com.macro.mall.user.User">bean>
    
beans>

创建对象是在bean标签下执行。它有两个常用字段

  • id:对象的唯一别名方便后面拿对象的时候根据指定的名称获取对象
  • class:类的地址值 反射机制就是通过class的地址值创建对象

调用类

    /**
     * 测试调用用户对象的test方法
     * IOC创建对象
     */
    public static void main(String[] args) {
        // 读取配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("test1.xml");
        // 生成对象
        User user = context.getBean("user", User.class);
        // 调用测试类的方法
        user.testCs();
    }


IOC默认是单实例对象。所以如果想要多实例就需要在bean标签设置一个scope=prototype
scope常用的两个字段prototypesingleton

  • singleton:默认类型。意思是在读取配置文件的时候就实例对象
  • prototype:只有在调用bean的时候才会实例对象

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    
    <bean id="user" class="com.macro.mall.user.User" scope="prototype">bean>

beans>

@注解工作流程
虽然配置文件可以实现。但是实现起来太过繁琐。需要写大量的配置。所以SpringIOC还有另一种方式就是使用注解代替配置也是工作常用的一种方式
常用注解:
对象创建注解 实现的效果都是一样的。如果你是小项目。随便使用那个都可以。如果你是大项目。就需要按照规范来做

  • @Component:当一个类不合适用以下的注解定义时用这个组件修饰
  • @Service:业务层 一般放在service接口的实现类上
  • @Controller:控制层 一般放在Controller上
  • @Repository:数据层 一般放在Dao接口的实现类上

属性注入注解 依赖注入这篇没有讲到。将会放到下篇单独的一章

  • @Autowored:根据类型注入
  • @Qualifier:根据名称注入,如果有多个类实现同一个接口。那么就可以使用Qualifier指定名称是那个实现类
  • @Resource:默认根据名称注入 如果没有则按照类型注入

Resource如果指定了name 那么就会到容器中匹配相对的name 如果没有则报错
Resource如果指定了type 那么就会到容器中匹配相对的type 没有则报错
Resource如果什么都没指定 默认先找名称。名称没有在找类型

组件扫描注解 想要实现全注解开发就需要将配置文件的组件扫描替换成注解扫描

  • @Configuration:将当前类当作配置类。代替xml配置文件
  • @ComponentScan:配置扫描的位置

开启注解扫描

/**
 * 开启全局扫描所有注解对象
 */
@Configuration
@MapperScan(basePackages = {"com.macro.mall"})
public class SpringConfig {
    
}

将类交给IOC容器

@Service(value = "user")
public class User

获取对象

    /**
     * 测试调用用户对象的test方法
     * IOC创建对象
     */
    @Test
    public void main1() {
        // 读取配置文件
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        // 生成对象
        User user = context.getBean("user", User.class);
        // 调用测试类的方法
        user.testCs();
    }


AOP-面向切面

通俗的讲就是AOP是面向切面编程。在不改变原代码的情况下。对业务增强。实现了业务层的消弱耦合 它的核心就是使用了动态代理生成一个代理对象 然后让代理对象对方法增强。
常用的注解

  • @Aspect:将当前类作为一个代理对象
  • @Order:如果有多个代理类对一个方法增强 那么order注解可以设置每个代理类的优先级 数值越低优先级越高
  • @Before:前置通知。在方法执行前执行
  • @AfterReturning:后置通知。在方法执行后执行
  • @AfterThrowing:异常通知。在方法报异常时执行
  • @After:最终通知。就好像finally一样不管正常还是异常都会执行 在最后执行
  • @Around:环绕通知。在方法执行前和执行后执行

前置通知

@Component
@Aspect // 将当前类作为一个代理对象
public class DaiLi {

    /**
     * 前置通知
     * value = "execution(* com.macro.mall.user.User.testCs())" 配置增强的方法
     * 也可以设置当前包下的所有的类的所有方法
     */
    @Before(value = "execution(* com.macro.mall.user.User.testCs())")
    public void qian(){
        System.out.println("在方法执行前执行。。。。。。。。");
    }
}

环绕通知

    /**
     * 环绕通知
     */
    @Around(value = "execution(* com.macro.mall.user.User.testCs())")
    public void hunRao(ProceedingJoinPoint proceedingJoinPoint){
        System.out.println("在方法执行前执行。。。。。。。。");

        try {
            // 增强的方法执行
            proceedingJoinPoint.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }

        System.out.println("在方法执行后执行。。。。。。。。");

    }

ps:一个开发界的小学生,一直在学习从未敢停止

你可能感兴趣的:(java)