Spring 两大特性IOC和AOP

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_30353203/article/details/84843441

IOC和AOP也需要个容器承载,spring相当这个容器,如果要用到这两个特性要在spring基础上去运行。

IOC

Spring通过控制反转(IOC)的技术促进了低耦合,一个对象依赖的其他对象会被通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。控制反转(Inversion of Control),是一种设计思想,一个重要的面向对象编程的法则,它能知道我们设计出松耦合的程序。传动应用程序都是由我们在类内主动创建依赖对象,从而导致类与类之间高耦合,难于测试,有了IOC容器之后,把创建和查找依赖对象的控制权,交个类容器,由容器进行注入组合对象,所以对象与对象之间就是松散耦合的,这样便于测试,功能复用,使整体程序体系结构变的灵活。DI(依赖注入)是实现Ioc的一种方法,控制反转是,获得依赖对象的方式反转了,其实Ioc对变成带来的最大改变不是从代码,是思想上,发生了“主从换位”的变化。应用程序原本是老大,要获得什么资源都是主动出击,但是Ioc/DI思想中,应用程序就变成被动的了,被动的等待Ioc容器来创建并注入所需要的资源了。

一、Bean的定义,<beans../>元素是spring配置文件的根元素,<beans.../>元素可以包含多个<bean..../>子元素。bean可以理解为实例化的对象,每一个Bean对应Spring容器里的一个Java实例,所以定义一个Bean需要有两个属性

Id,确定该Bean的唯一标识符,容器对Bean管理、访问、以及该Bean的依赖关系,都通过该属性完成,Bean的id属性在Spring容器中是唯一的。

Class,指定new的哪一个类,不能是接口类,spring会直接使用new关键字创建改Bean的实例,因此,这里必须提供Bean实现类的类名。例如,在配置一个Bean时,该Bean实现类中必须有个一个无参构造器,可以没有构造方法,如果有构造方法了,必须有一个无参数的构造方法

<bean id="bookDao" class="com.service.impl.BookDao"/>

容器的启动,暂时没用用tomcat容器,所以用spring自带的容器启动它,默认去resources

 ApplicationContext context = new ClassPathXmlApplicationContext("IOCBeans01.xml");

通过xml注入的两种方式

一个是注解扫包

<bean id="bookDao" class="com.service.impl.BookDao"/>
    <context:component-scan base-package="com.service.impl" />

把bookDao这个bean 赋值给@Autowired注解下面的那个成员变量

一个是xml配置

 <bean id="bookService" class="com.service.impl.BookService">
        <property name="iBookDao" ref="bookDao"></property>
    </bean>

把bookDao这个bean,赋值给iBookDao这个成员变量

二、参数传递

constructor-arg 代表构造方法 和值

property name 代表set方法

 <bean id="userDao" class="com.service.impl.UserDao">
        <constructor-arg name="" value=""/>
        <property name="" value=""/>
    </bean>

三、Bean回调方法

回调方法,在初始化这个bean的时候,先执行一个方法

执行测试的时候,去启动容器,在启动容器过程中,就会出现new的这个操作,只针对这个bean自己初始化用

  <bean id="userService" class="com.service.impl.UserService"
        init-method="initMethod" destroy-method="destroyMethod">
        <property name="iUserDao" ref="userDao"/>
    </bean>
  public void initMethod(){
        System.out.println("初始化操作");
    }
    public void destroyMethod(){
        System.out.println("关闭方法");
    }
 UserService userService = context.getBean("userService",UserService.class);

这个getBean里的是xml里配置的id,如果没有提供名字,就用spring默认的命名机制,即类名的第一个字母小写,强制类型转换,getBean拿到的是一个object类型,需要做类型转化,有两种方式,第一种在bean的名字后面加上UserService.class, 第二种在前面(UserService) context.getBean("userService")

四、使用Spring注解配置IOC

首先要在xml中配置扫描包,使用注解情况下要加这个扫描,

 <context:component-scan base-package="com.service.impl" />

注解分为三类

@Repository用于DAO层的实现类进行注解

@Service用于业务层注解,功能和@Component

@Controller用于控制层注解,功能和@Component

五、初始化回调注解与销毁回调注解

 @PostConstruct
    public void initMethod(){
        System.out.println("构造方法之后执行,初始化");
    }
    @PreDestroy
    public void destroyMethod(){
        System.out.println("销毁之前执行");
    }

销毁是当bean被处理掉了之后,就会执行,跟执行什么方法没有关系

注解@PostConstruct等同于 xml里的 init-method="initMethod"

注解@PreDestroy 等同于xml里的destroy-method="destroyMethod"

六、自动装配/注入

使用注解@Autowired

七、零配置实现IOC

八、通过注解@Value获取properties配置

取properties里的值步骤

首先要有一个properties文件 ,类似一个map对象,key-value

然后新建一个包下面一个类,属性和properties里的一样 ,类用@Componet 组件的意思 扫描包, 添加get set  toString 然后用spring初始化 注解@PostConstruct,输出,

然后新建一个xml ,用扫描包和位置的标签 

component-scan base-package=   

资源点位,资源的位置

property-placeholder location=“config/config.properties”

创建一个测试类 

ApplicationContext applicationContext;

applicationContext = new ClassPathXmlApplicationContext(config.xml);

九、bean作用域

十、扫描过滤expression表达式

spring 注入bean的方式两种xml写法,一种是,相当对这个iBookDao成员变量赋值,把bookDao这个bean注入到bookService这个类里

 <bean id="bookDao" class="com.service.impl.BookDao"/> 
 <bean id="bookService" class="com..service.impl.BookService">
        <property name="iBookDao" ref="bookDao"></property>
    </bean>

一种是注解方式,扫描包,在对应的类里的成员变量加上注解@Autowired,扫描到这个成员变量。@Autowired是按照类型注入的

<bean id="bookDao" class="com.service.impl.BookDao"/>
    <context:component-scan base-package="com.service.impl" />

AOP

AOP(Aspect Oriented Programming)面向切面编程,什么地方应用,一般应用在日志。避免重复代码,较少对业务代码的入侵

AOP的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: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">


<context:component-scan base-package="com..service.impl"></context:component-scan>
    <!--当有切面被触发的时候去执行这类里面的方法,有了切面之后需要一个类(bean)去承载执行-->
    <bean id="halder" class="com.long.lesson.service.Halder"/>
    <aop:config>
        <!-- 切入点,在什么情况下去执行aop的内容-->
        <aop:aspect id="time" ref="halder">
            <!--切入点,在触发什么条件下进入切入点-->
            <!--切入点表达式主要是触发条件,含义是Service类里面的所有方法,并且需要带参数才会切入-->
            <!--id的值,和下面的pointcut-ref的值是一致的,说明before 和after执行的切点是id相同的那个
                 id和pointcut-ref 是一一对应的-->
            <aop:pointcut id="addAllMethod"
                          expression="execution(* com.long.lesson.service.impl.*Service.*(*))"/>
            <!--method的值是 切面类里的方法 -->
            <!--before是在执行UserService里add方法之前,aop介入-->
            <aop:before method="startTime" pointcut-ref="addAllMethod"/>
            <!--after是在执行UserService里add方法之后,aop介入-->
            <aop:after method="endTime" pointcut-ref="addAllMethod"/>
            <!--环绕是在执行UserService里add方法之前之后,都介入aop-->
            <aop:around method="aroundTest" pointcut-ref="addAllMethod"/>
        </aop:aspect>
    </aop:config>
</beans>


import org.aspectj.ProceedingJoinPoint;
import javax.xml.crypto.Data;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * Created by on 2018/12/22.
 */
//一把菜刀
public class Halder {
    public void startTime(){
        long startTime =System.currentTimeMillis();
        System.out.println("开始执行时间:"+new Date());
    }
    public void endTime(){
        long endTime =System.currentTimeMillis();
        System.out.println("结束执行时间:"+new Date());
    }

    //环绕通知
    public Object aroundTest(ProceedingJoinPoint proceedingJoinPoint){
   //
   //   System.err.println("环绕通知进来的参数"+proceedingJoinPoint.getArgs());
   //   拿目标类
   //   System.err.println(proceedingJoinPoint.getTarget());
   //   拿目标方法
   //   System.err.println(proceedingJoinPoint.getSignature().getName());
        Object arg = proceedingJoinPoint.getArgs()[0];
        String s = (String)arg;
        System.err.println("原来的环绕通知进来的参数:"+s);
        Object[] args = proceedingJoinPoint.getArgs();
        args[0]="你好我是环绕通知修改后的参数:";
        
        try {
    //        System.err.println("我是调用:"+proceedingJoinPoint.getSignature().getName()+"之前的输出");
         // 去执行目标方法的处理,执行proceed()之后去调用add方法
            Object o = proceedingJoinPoint.proceed(args);
            List list = (List)o;
            list.clear();
            list.add("哈哈哈,我是修改后的返回参数");
            System.err.println(o);
    //        System.err.println("我是调用:"+proceedingJoinPoint.getSignature().getName()+"之后的输出");
            return o;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_30353203/article/details/84843441
今日推荐