Java架构学习(二十三)Spring核心技术&SpringIOC&DI&依赖注入&单例模式&SpringAOP&注解注入

版权声明:本文为博主原创文章,未经博主允许不得转载。如需要授权请联系[email protected] https://blog.csdn.net/leeue/article/details/81665473

SpringIOC和AOP

一、Spring核心技术

Spring核心技术:springIOC、DI、AOP还有事务管理、传播行为。

什么是Spring?
答:spring是一个容器,管理每个bean(对象)与bean(对象)之间的关系。
   使用spring来管理。

在没有使用Spring的时候使用的三层架构。

这里写图片描述

这上面因为对象太多,不方便管理。所以才会使用Spring框架。

Spring好处:解耦、对象是单例的可以节约内存。
任何对象初始化的过程,全部交给Spring,用了Spring框架后,
就不能使用User user = new User();这种初始化方式了。

二、SpringIOC介绍

SpringIOC与DI(面试问)

什么是IOC?
答:IOC就是控制反转,将bean的对戏那个交给Spring容器进行管理。
   IOC实现的原理是反射机制。
   反射:创建对象。
什么是DI?
答:DI就是依赖注入。
   解决对象之间的依赖关系,就比如userService依赖userDao。

三、SpringIOC依赖注入

项目如图所示:

这里写图片描述

第一步:创建UserEntity这个实体类
第二步:创建Spring.xml
第三步:在Spring.xml里面注入UserEntity这个实体类。如图

这里写图片描述

测试:当初手写SpringIOC也写过。这个对象就是通过Spring这个容器创建的

这里写图片描述

如果sporing.xml文件里,配置相同的bean id的时候会报错。如图。

这里写图片描述

第四、Spring创建对象的单例和多例作用域

Spring默认创建对象是单例的,可以去在spring.xml文件中修件。修改。

Spring的作用域。4种作用域。
单例:jvm只能创建一次,且只存在一个。
多例:每次运行都会创建一次。存在多个。
request:请求作用域在请求里才有效的。
session:对象和session绑定的,session什么时候失效,
        对象就什么时候失效。

证明对象是单例的?直接去查看构造函数。执行一遍就是单例的。

使用单例模式注意事项:
答:饿汉式是天生线程安全的。因为饿汉是一开始就创建对象的。
   饱汉式是线程不安全的。

spring使用的是饿汉式来创建对象。

将spring设置成多例的:
<bean id="userEntity1" class="com.leeue.entity.UserEntity" 
scope="prototype">
</bean>

多例是不会产生线程安全的,因为多例每次都是新的对象。

第五、SpringIOC依赖注入

注入的方式有:
1、通过构造函数
2、通过set方法属性注入值
3、p名称空间
4、注解
SpringIOC创建对象默认走无参构造函数。
SpringIOC有参构造函数。

使用SpringIOC调用有参构造函数

对象:
这里写图片描述
spring.xml配置:
这里写图片描述

依赖DI 就是给对象做关联关系的

一、使用set方法做依赖注入:
    案例:在service里注入dao。然后调用add方法。
    DI:就是建立起依赖关系。

UserDao层:
这里写图片描述
UserService层:
这里写图片描述
spring.xml文件配置:
这里写图片描述

测试:
这里写图片描述

使用注解方式注入

如果包名不同,注入的id相同,默认使用第一个注入的。

配置包扫描:

这里写图片描述

这里写图片描述

报错:
这里写图片描述

@Autowired:默认是以类型来查找对象的
@Resource:是根据名称来查找对象的。 这个注解在jdk1.6之后才有,1.5是用不了的。
@Resource(name=”userDao02”)

@Autowired(required=false)@Qualifier("userDao02")
禁止类型查找,也通过名称来查找。

所以这里解决报错的方法就是加上标识符,使用@Resource来注入.

这里写图片描述
这里写图片描述
这里写图片描述

第六、SpringAOP

什么是代理设计模式?
答:作用:提供对目标对象进行访问的方式。(中介类似)
   好处:提高安全性。

静态代理与动态代理的区别?
答:静态代理:需要生成代理类。需要自己创建对象
    动态代理:不需要生成代理类。直接使用object

动态代理:
    jdk动态代理:反射机制。
    cglib动态代理:字节码。


什么是springAOP?
答:面向切面编程   --思想

应用场景:权限管理、事务管理、日志打印、性能监控。


什么地方项目才会使用aop?
答:重复代码。代码冗余。在不同的方法中,但是需要做相同的操作。
关注点:重复代码的地方。
切面:相当于把重复的代码抽取出来。
切入点:拦截哪些方法。

SpringAOP方式:注解方式、xml方式。

SpringAOP通知:
前置通知:
后置通知:
异常通知:
环绕通知:
运行通知:


切面编程使用方式:
第一步:在spring.xml开启aop事务权限
<!-- 开启aop事务注解,才能使用aop切面编程 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
第二步:定义切面
package com.leeue;

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

/**
 * 
 * @classDesc: 功能描述:(切入点)
 * @author:<a href="[email protected]">李月</a>
 * @Version:v1.0
 * @createTime:2018年8月14日 下午4:43:43
 */
@Aspect//定义成切面,表示这个是个切面
@Component//表示把这个类注入到spring容器中。
public class Aop01 {

    //Spring Aop通知?
    /**
     * 前置通知
     */
    @Before(value = "execution(* com.leeue.service.UserService.add(..) )")
    public void bean() {
        System.out.println("前置通知......");
    }
    /**
     *后置通知
     */
    @After(value = "execution(* com.leeue.service.UserService.add(..) )")
    public void commit() {
        System.out.println("后置通知.....");
    }
    /**
     * 运行通知
     */
    @AfterReturning(value = "execution(* com.leeue.service.UserService.add(..) )")
    public void afterRunning() {
        System.out.println("运行通知.....");
    }
    /**
     * 异常通知
     */
    @AfterThrowing(value = "execution(* com.leeue.service.UserService.add(..) )")
    public void afterThrowing() {
        System.out.println("异常通知.....");
    }
    /**
     * 环绕通知
     * @throws Throwable 
     */
    @Around(value = "execution(* com.leeue.service.UserService.add(..) )")
    public void around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕通知......前");
        point.proceed();//这个就是 执行 add 方法,如果没有就不执行 应用场景在权限,有权限就走
        System.out.println("环绕通知......后");

    }


}
使用xml方式来做切面编程

spring.xml

<?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:p="http://www.springframework.org/schema/p"
    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">





    <bean id="userEntity1" class="com.leeue.entity.UserEntity"></bean>

    <bean id="userEntity2" class="com.leeue.entity.UserEntity">
        <constructor-arg name="userName" value="leeue"></constructor-arg>
        <constructor-arg name="age" value="23"></constructor-arg>
    </bean>

    <bean id="userDao" class="com.leeue.dao.UserDao"></bean>

    <bean id="userService" class="com.leeue.service.UserService">
        <property name="userDao" ref="userDao"></property>
    </bean>


    <!-- 配置扫包 扫描包的范围 -->
    <context:component-scan base-package="com.leeue"></context:component-scan>


    <!-- 开启aop事务注解,才能使用aop切面编程 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    <!-- 切面类 -->
    <bean id="aop" class="com.leeue.Aop02"></bean>

    <aop:config>
        <!-- 定义一个切入点表达式: 拦截哪些方法 -->
        <aop:pointcut expression="execution(* com.leeue.service.UserService.add(..) )" id="pt"/>
        <!-- 切面 -->
        <aop:aspect ref="aop">
            <!-- 环绕通知 -->
            <aop:around method="around" pointcut-ref="pt"/>
            <!-- 前置通知: 在目标方法调用前执行 -->
            <aop:before method="begin" pointcut-ref="pt"/>
            <!-- 后置通知: -->
            <aop:after method="after" pointcut-ref="pt"/>
            <!-- 运行通知 -->
            <aop:after-returning method="afterReturning" pointcut-ref="pt"/>
            <!-- 异常通知 -->
            <aop:after-throwing method="afterThrowing" pointcut-ref="pt"/>

        </aop:aspect>
    </aop:config>


</beans>

Aop02.java

package com.leeue;

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

/**
 * 
 * @classDesc: 功能描述:(使用xml方式来实现切面编程)
 * @author:<a href="[email protected]">李月</a>
 * @Version:v1.0
 * @createTime:2018年8月14日 下午4:43:43
 */
public class Aop02 {

    public void begin() {
        System.out.println("前置通知......");
    }

    public void after() {
        System.out.println("后置通知.....");
    }

    public void afterReturning() {
        System.out.println("运行通知.....");
    }

    public void afterThrowing() {
        System.out.println("异常通知.....");
    }

    public void around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕通知......前");
        point.proceed();//这个就是 执行 add 方法,如果没有就不执行 应用场景在权限,有权限就走
        System.out.println("环绕通知......后");
    }


}

猜你喜欢

转载自blog.csdn.net/leeue/article/details/81665473