当前位置: 澳门新濠3559 > 编程 > 正文

由ioc容器帮我们实现对象的创建、注入等过程,

时间:2019-10-07 13:13来源:编程
Spring是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为J2EE 应用程序开发提供集成的

Spring是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。

配置ehcache与redis

图片 1三大核心组件.png

拦截器和过滤器.png

图片 2Spring的7个模块.png图片 32、常用模块.png

核心组件协同工作

先来回顾一下拦截器与过滤器。如下图一网友的测试,在web.xml中注册了TestFilter1和TestFilter2。然后在spring的配置文件中配置了BaseInterceptor和TestInterceptor。得到的结果如下图所示。从图中可以看出,拦截器和过滤器都横切了业务方法,看似符合aop的思想。

最后的最后,欢迎关注我的微信公众号java-mindmap,更多java思维导图与项目资料供你学习,每三到四天会更新一篇,带你走进记忆脑图的世界。

@CachePut(value = "user", key = "#id", condition = "#result.username ne 'zhang'")  
public User conditionSave(final User user)   

如果说在三个核心中再选出一个核心,那就非Bean莫属了。可以说,Spring就是面向Bean的编程,Bean在Spring中才是真正的主角。

相比xml配置,基于注解的方式更加简洁方便。

关于Spring

  • 小试牛刀,综合运用:

Spring为何如此流行?你会发现Spring解决了一个非常关键的问题,它可以让你对对象之间的关系转而用配置文件来管理,或者注解,也就是它的依赖注入机制。而这个注入关系在一个叫Ioc的容器中管理。Ioc容器就是被Bean包裹的对象。Spring正是通过把对象包装在Bean中从而达到管理这些对象及做一些列额外操作的目的。

JDK动态代理

写在前面

缓存对比.png

图片 4Spring知识细节.png

@Aspect
public class TransactionDemo {

    @Pointcut(value="execution(* com.yangxin.core.service.*.*.*(..))")
    public void point(){

    }

    @Before(value="point()")
    public void before(){
        System.out.println("transaction begin");
    }

    @AfterReturning(value = "point()")
    public void after(){
        System.out.println("transaction commit");
    }

    @Around("point()")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("transaction begin");
        joinPoint.proceed();
        System.out.println("transaction commit");
    }
}

常用注解

缓存是实际工作中非常常用的一种提高性能的方法。而在java中,所谓缓存,就是将程序或系统经常要调用的对象存在内存中,再次调用时可以快速从内存中获取对象,不必再去创建新的重复的实例。这样做可以减少系统开销,提高系统效率。

3种注入方式

Spring 的 AOP 代理由 Spring 的 IoC 容器负责生成、管理,其依赖关系也由 IoC 容器负责管理。因此,AOP 代理可以直接使用容器中的其他 Bean 实例作为目标,这种关系可由 IoC 容器的依赖注入提供。

图片 5公众号回复“思维导图”下载源xmind导图

公众号回复“思维导图”下载源xmind导图

  • Setter方法注入
  • 构造器注入

拦截器与过滤器.png

最后

由ioc容器帮我们实现对象的创建、注入等过程,数据库查询占据了数据库操作的80%以上。如下@CacheEvict, beforeInvocation=false表示在方法执行之后调用(#result能拿到返回值了);且判断condition,如果返回true,则移除缓存;

图片 6Spring 整体结构图.jpg

下篇文章将会写Spring cache的内容,同样以思维导图的方式编写。可视化学习,让java不再难懂。

图片 76、第三方框架集成.png

    @CachePut(value = "user", key = "#user.id")
    public User save(User user) {
        users.add(user);
        return user;
    }

    @CachePut(value = "user", key = "#user.id")
    public User update(User user) {
        users.remove(user);
        users.add(user);
        return user;
    }

    @CacheEvict(value = "user", key = "#user.id")
    public User delete(User user) {
        users.remove(user);
        return user;
    }

    @CacheEvict(value = "user", allEntries = true)
    public void deleteAll() {
        users.clear();
    }

    @Cacheable(value = "user", key = "#id")
    public User findById(final Long id) {
        System.out.println("cache miss, invoke find by id, id:"   id);
        for (User user : users) {
            if (user.getId().equals(id)) {
                return user;
            }
        }
        return null;
    }
 下面有关spring的依赖注入,说法错误的是? A、依赖注入通常有如下两种:设置注入和构造注入: B、构造注入可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入 C、当设值注入与构造注入同时存在时,先执行构造注入,再执行设值注入 D、设值注入是指IoC容器使用属性的setter方法来注入被依赖的实例。这种注入方式比较简单、直观

Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。

图片 81、Spring特征.png

context的初始化过程

当运行ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); 构造方法ClassPathXmlApplicationContext(String configLocation)调用了this(new String[] {configLocation}, true, null);, 该构造方法具体代码如下。

图片 9ClassPathXmlApplicationContext构造方法.jpg图片 10refresh()方法.jpg

观察一下传统编码方式与使用aop的区别

Sping架构

根据运行流程,如下@Cacheable将在执行方法之前( #result还拿不到返回值)判断condition,如果返回true,则查缓存;

牛客网给出的答案是选C,不过网友们好像对答案有不同的意见哈。查看网友评论及答案

Spring默认采取的动态代理机制实现AOP,当动态代理不可用时(代理类无接口)会使用CGlib机制。

bean注入与装配的的方式有很多种,可以通过xml,getset方式,构造函数或者注解等。简单易用的方式就是使用Spring的注解了,Spring提供了大量的注解方式,让项目阅读和开发起来更加方便。

项目中注解缓存只能配置一个,所以可以通过以下引入哪个配置文件来决定使用哪个缓存。

控制反转

通过上面的分析,大家是否有种熟悉的感觉,似乎和拦截器、过滤器的功能相似。那么问题来了,aop与拦截器、过滤器是什么关系。

Spring3与Spring4是有区别的,4.0主要是对Java 8的新函数式语法进行支持,还有加强了对网络各种新技术比如http-streaming, websocket的更好的支持。

缓存注解.png

就好像我们无需考虑对象的销毁回收一样,因为java垃圾回收机制帮助我们实现了这个过程;而ioc则是让我们无需考虑对象的创建过程,由ioc容器帮我们实现对象的创建、注入等过程。

知识拓展

图片 113、主要jar包.png

关于缓存

Spring的代码还真是不好读,分得太细了,文字也是难以描述出来,看了别人有关的博客,贴了好多代码,画了好多ER图来描述关键接口或类之间的关系。这么一篇这么长文章下来,大家也未必会认真读代码,看ER图,干脆也不跟风了。就贴了一点在我看来特关键的代码,嘿嘿。

在applicationContext.xml中配置。

一般来说,Spring主要分为7个模块:

<import resource="classpath:spring/spring-ehcache.xml"/>
<!-- <import resource="classpath:spring/spring-redis.xml"/>-->

spring ioc容器

什么是aop

图片 124、常用注解.png图片 135、装配注解比较.png

从以上的注解中可以看出,虽然使用注解的确方便,但是缺少灵活的缓存策略,

IOC中最核心的接口是Beanfactory提供IOC的高级服务,而ApplicationContext是建立在BeanFactory基础之上提供抽象的面向应用的服务。

而AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

这一节简单介绍了Spring,没涉及到原理的东西。Spring如此博大精深,希望大家好好学习哈。

  • spring cache集成redis,spring-redis.xml主要内容:

写到这里,让我想起了最近在牛客网上看的一道选择题了:

  • JDK动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。InvocationHandler是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编制在一起。

  • Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。

Spring框架是分模块存在,除了最核心的Spring Core Container(即Spring容器)是必要模块之外,其他模块都是可选,视需要而定。大约有20多个模块。

  • spring cache集成ehcache,spring-ehcache.xml主要内容:

BeanFactory与ApplacationContext的区别

使用aop可以做的事情有很多。

相关文章阅读

<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache-core</artifactId>
    <version>${ehcache.version}</version>
</dependency>

<!-- Spring提供的基于的Ehcache实现的缓存管理器 -->

<!-- 如果有多个ehcacheManager要在bean加上p:shared="true" -->
<bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
     <property name="configLocation" value="classpath:xml/ehcache.xml"/>
</bean>

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
     <property name="cacheManager" ref="ehcacheManager"/>
     <property name="transactionAware" value="true"/>
</bean>

<!-- cache注解,和spring-redis.xml中的只能使用一个 -->
<cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>

图片 14BeanFactory 与ApplacationContext.png

关注我的简书吧,与我共同学习。

很多人在微信公众号中给我留言说想看spring的思维导图,正好也打算写。与其他框架相比,spring项目拥有更多的模块,我们常用的ioc,mvc,aop等,这些是spring的主要板块。一篇文章也不可能全部都讲,所以,我打算先把spring简介说一下,后续再写ioc,mvc和aop。

写在最后

从时序图来看启动上述初始化

图片 15容器初始化时序图.jpg

写在最后

下篇文章将会写Spring mvc的内容,同样以思维导图的方式编写。可视化学习,让java不再难懂。

关注我的简书吧,与我共同学习哈哈。

上篇文章阅读

  • Spring思维导图,让spring不再难懂

(PS:公众号回复“思维导图”可以下载源文件)

图片 16公众号回复“思维导图”下载源xmind导图

  • Spring思维导图,让Spring不再难懂(mvc篇)

  • Spring思维导图,让Spring不再难懂(ioc篇)

  • Spring思维导图,让spring不再难懂(一)

Spring框架的开发不是为了替代现有的优秀第三方框架,而是通过集成的方式把它们都连接起来。下面总结了一些常集成的优秀框架。

  • 数据库通常是企业应用系统最核心的部分
  • 数据库保存的数据量通常非常庞大
  • 数据库查询操作通常很频繁,有时还很复杂

写在前面

aop使用场景

(PS:公众号回复“思维导图”可以下载源文件)

关注java思维导图简书或微信公众号,与我共同学习。

当然,有了注解之后,使用注解的方式更加方便快捷。即自动装配功能实现属性自动注入(@autowire)。

  • 性能监控,在方法调用前后记录调用时间,方法执行太长或超时报警。
  • 缓存代理,缓存某方法的返回值,下次执行该方法时,直接从缓存里获取。
  • 软件破解,使用AOP修改软件的验证类的判断逻辑。
  • 记录日志,在方法执行前后记录系统日志。
  • 工作流系统,工作流系统需要将业务代码和流程引擎代码混合在一起执行,那么我们可以使用AOP将其分离,并动态挂接业务。
  • 权限验证,方法执行前验证是否有权限执行当前方法,没有则抛出没有权限执行异常,由业务代码捕捉。
  • 开源项目spring-shiro-training思维导图,让项目不再难懂
  • java基础思维导图,让java不再难懂
  • mybatis思维导图,让mybatis不再难懂
  • mybatis思维导图,让mybatis不再难懂

spring cache特性与缺憾

在Spring框架中,依赖注入的设计模式是用来定义对象彼此间的依赖。使用xml配置bean的情况下,它主要有两种类型:

写在最后

图片 17Spring 3.2.17.RELEASE.png图片 18Spring 4.2.7.RELEASE.png

以思维导图的方式,可视化学习,让java不再难懂。

原理解析

为了理清关系,先来个类关系图。

它是一个全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层。但是Spring仍然可以和其他的框架无缝整合。

如下@CachePut将在执行完方法后(#result就能拿到返回值了)判断condition,如果返回true,则放入缓存

在Spring框架中的核心组件只有三个:Core、Context和Bean。它们构建起了整个Spring的骨骼架构,没有它们就不可能有AOP、Web等特性功能。

简单例子

Spring的主要jar包

更加详细的使用与配置,可以参考项目中spring-shiro-training中有关spring cache的配置。

图片 19ioc容器.png图片 20spring ioc初始化.png图片 21spring ioc容器工作原理.jpg

通过前面介绍可以知道:AOP 代理其实是由 AOP 框架动态生成的一个对象,该对象可作为目标对象使用。AOP 代理包含了目标对象的全部方法,但 AOP 代理中的方法与目标对象的方法存在差异:AOP 方法在特定切入点添加了增强处理,并回调了目标对象的方法。

第三方框架集成

@Cacheable(value = "user", key = "#id", condition = "#id lt 10")  
public User conditionFindById(final Long id)  

写过java的都知道:所有的对象都必须创建;或者说:使用对象之前必须先创建。而使用ioc之后,你就可以不再手动创建对象,而是从ioc容器中直接获取对象。

<aop:aspectj-autoproxy />
<bean id = "transactionDemo" class = "com.yangxin.core.transaction.TransactionDemo" />

缓存不同层级的作用.png

图片 22Spring ioc简介.png

什么是aop.png

如下@CachePut将在执行完方法后(#result就能拿到返回值了)判断unless,如果返回false,则放入缓存;(即跟condition相反)

两种动态代理方式

特性与缺憾.png

描述AOP常用的一些术语有通知(Adivce)、切点(Pointcut)、连接点(Join point)、切面(Aspect)、引入(Introduction)、织入(Weaving)、通知(Advice)等。

  • https://git.oschina.net/wangzhixuan/spring-shiro-training.git

Spring中主要的AOP组件.png

项目中可能有很多缓存的TTL不相同,这时候就需要编码式使用编写缓存。

aop重要概念.png

条件缓存

  • 定义普通业务组件。
  • 定义切入点,一个切入点可能横切多个业务组件。
  • 定义增强处理,增强处理就是在 AOP 框架为普通业务组件织入的处理动作。

(PS:公众号回复“思维导图”可以下载源文件)

AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

  • TTL(Time To Live )
    存活期,即从缓存中创建时间点开始直到它到期的一个时间段(不管在这个时间段内有没有访问都将过期)

  • TTI(Time To Idle)
    空闲期,即一个数据多久没被访问将从缓存中移除的时间

CGLib动态代理

现在市场上主流的缓存框架有ehcache、redis、memcached。spring cache可以通过简单的配置就可以搭配使用起来。其中使用注解方式是最简单的。

(PS:公众号回复“思维导图”可以下载源文件)

上篇文章阅读

  • AspectJ
  • JBoss AOP
  • Spring AOP

缓存策略:

3种日志处理.png

当然,可以通过其他配置搭配使用两个缓存机制。比如ecache做一级缓存,redis做二级缓存。

spring aop原理

在增删改查中,数据库查询占据了数据库操作的80%以上,而非常频繁的磁盘I/O读取操作,会导致数据库性能极度低下。而数据库的重要性就不言而喻了:

aop框架种类

aop开发时,其中需要程序员参与的只有 3 个部分:

Cache注解

代理的方法与目标对象的方法.png

在系统架构的不同层级之间,为了加快访问速度,都可以存在缓存

Filter过滤器:拦截web访问url地址。
Interceptor拦截器:拦截以 .action结尾的url,拦截Action的访问。
Spring AOP拦截器:只能拦截Spring管理Bean的访问(业务层Service)

  • Spring思维导图,让Spring不再难懂(aop篇)
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • Spring思维导图,让Spring不再难懂(ioc篇)
  • Spring思维导图,让spring不再难懂(一)

核心概念

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.8.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.4.2</version>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>

<!-- 注意需要添加Spring Data Redis等jar包 -->
<description>redis配置</description>

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <property name="maxIdle" value="${redis.pool.maxIdle}"/>
    <property name="maxTotal" value="${redis.pool.maxActive}"/>
    <property name="maxWaitMillis" value="${redis.pool.maxWait}"/>
    <property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/>
    <property name="testOnReturn" value="${redis.pool.testOnReturn}"/>
</bean>

<!-- JedisConnectionFactory -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    <property name="hostName" value="${redis.master.ip}"/>
    <property name="port" value="${redis.master.port}"/>
    <property name="poolConfig" ref="jedisPoolConfig"/>
</bean>

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
      p:connectionFactory-ref="jedisConnectionFactory">
    <property name="keySerializer">
        <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean>
    </property>
    <property name="valueSerializer">
        <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
    </property>
    <property name="hashKeySerializer">
        <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
    </property>
    <property name="hashValueSerializer">
        <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
    </property>
</bean>

<!--spring cache-->
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"
      c:redisOperations-ref="redisTemplate">
    <!-- 默认缓存10分钟 -->
    <property name="defaultExpiration" value="600"/>
    <property name="usePrefix" value="true"/>
    <!-- cacheName 缓存超时配置,半小时,一小时,一天 -->
    <property name="expires">
        <map key-type="java.lang.String" value-type="java.lang.Long">
            <entry key="halfHour" value="1800"/>
            <entry key="hour" value="3600"/>
            <entry key="oneDay" value="86400"/>
            <!-- shiro cache keys -->
            <entry key="authorizationCache" value="1800"/>
            <entry key="authenticationCache" value="1800"/>
            <entry key="activeSessionCache" value="1800"/>
        </map>
    </property>
</bean>

<!-- cache注解,和spring-ehcache.xml中的只能使用一个 -->
<cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>
  • CGLib全称为Code Generation Library,是一个强大的高性能,高质量的代码生成类库,可以在运行期扩展Java类与实现Java接口,CGLib封装了asm,可以再运行期动态生成新的class。和JDK动态代理相比较:JDK创建代理有一个限制,就是只能为接口创建代理实例,而对于没有通过接口定义业务方法的类,则可以通过CGLib创建动态代理。
@CacheEvict(value = "user", key = "#user.id", beforeInvocation = false, condition = "#result.username ne 'zhang'") 
public User conditionDelete(final User user)   

上篇文章阅读

@CachePut(value = "user", key = "#user.id", unless = "#result.username eq 'zhang'")  
public User conditionSave2(final User user)   

公众号回复“思维导图”下载源xmind导图

编辑:编程 本文来源:由ioc容器帮我们实现对象的创建、注入等过程,

关键词: 澳门新濠3559