第三十一天 Java基础学习(二十五)

一、Mybatis中拦截器的支持

     过滤器和拦截器作用都差不太多 都是在某一个目标操作之前 会执行一些列内容

    过滤器依赖于Tomcat容器 拦截器是可以在javaSE项目中使用 不依赖于Tomcat容器 

●创建分页参数工具类

创建com.bjsxt.interceptor.MyPageHelper。

MyPageHelper类名称自定义的。作用为了设置分页的条件。没有这个类,实现的分页必须写成固定值。全局变量设置为protected表示同包能方法,此类会和插件类放在一个包下。

startPage提供的静态方法,方便以后设置分页的条件。

●创建插件实现类

新建com.bjsxt.interceptor.MyPageHelperInterceptor。

注意下类上面的注解。

@Intercepts 表示当前是一个拦截器。

@Signature表示签名。

type:拦截器主要拦截的类型,可以是四大核心接口。

method:拦截type中的哪个方法

args:method对应方法的参数。这个很重要,因为Java支持方法重载,不设置参数可能无法精确到具体的方法。

●配置插件 java

在MyBatis全局配置文件中配置插件,如果不配置,插件是无法被识别的。

需要把<plugins>标签配置在<environment>标签的上面。这点是DTD的要求。

里面的属性对于当前演示没有实际作用,单纯为了演示如果传递属性。

●查看控制台结果

通过控制台效果图可以看出来

1.能够成功获取配置插件时的属性值

2.在自己定义的SQL后面拼接上了1imit关键字

●使用PageHelper分页插件步骤

•导入依赖

<dependency>

<groupId>com.github.pagehelper</groupId>

<artifactId>pagehelper</artifactId>

<version>5.3.0</version>

</dependency>

•在mybatis.xml中进行配置

<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>

●在代码中使用即可

查询之前 添加:PageHelper.startPage(2,2);

查询之后可以在PageInfo<Clazz> info=new PageInfo<>(list);对象中获得分页相关信息

二、Spring框架

Spring Framework其主要目的是为了简化项目开发。

主要是为了不使用EJB下依然能够构建高质量Java EE项目。

●Spring各个模块

•Test

对应spring-test.jar. Spring提供的测试工具,可以整合JUnit测试,简化测试环节.

•Core Container

Spring的核心组件,包含了Spring框架最基本的支撑.

Beans,对应spring-beans.jar.Spring进行对象管理时依赖的jar包.

Core,对应spring-core.jar,Spring核心jar包.

Context,对应spring-context.jar, Spring容器上下文对象。

SpEL,对应spring-expression.jar,Spring表达式语言.

•AOP

面向切面编程,对应spring-aop.jar.

•Aspects

Aspect的具体实现,面向切面编程的另一种实现。对应spring-aspects.jar

•Instrumentation

服务器代理接口的具体实现。对应spring-instrument.jar 

•Messaging

集成messaging api和消息协议提供支持。对应spring-messaging.jar

•Data Access/Integration

Spring对数据访问层的封装

JDBC,对应spring-jdbc.jar.Spring对jdbc的封装,当需要使用spring连接数据库时使用.spring-jdbc.jar需要依赖spring-tx.jar.Transactions,对应spring-tx.jar.事务管理

ORM,对应spring-orm.jar.spring整合第三方orm框架需要使用的jar包,例如Hibernate框架.

•Web

Spring对javax下的接口或类做的扩展功能.

spring-web.jar,对Servlet, filter,Listener等做的增强

spring-webmvc.jar,实际上就是SpringMVC框架.需要依赖spring环境和spring-web.jar

●SpringDI 依赖注入的方式

•构造注入

name:需要和对应构造方法中形参名称保持一致

value:赋予属性的值 

index:属性对应的下标 

type:属性对应的类型

如果我们注入的值是常用类型(例如基本数据类型、对应包装类、String)使用value如果给某些对象注入值的时候 使用ref

•SET方法

name:和对应类中SET方法名称保持一致

三、Spring loC/DI

loC(Inversion of Control)中文名称:控制反转。也被称为DI(dependency injection)依赖注入。属于同一件事情的两个名称。

loC/DI是指一个过程:对象的创建仅仅通过Spring容器负责,Spring容器可以通过对象的构造方法或工厂方法进行实例化对象。

在创建对象过程中,如果对象需要依赖其他对象,也可以直接在Spring容器中注入到当前对象。

整个过程中对象本身在容器中控制自己的实例化(所以叫做控制反转),通过构造方法或setter方法把依赖对象注入到自己(所以又叫做依赖注入)

●容器(Container):放置所管理对象的对象。其本质是在容器对象里面有一个全局Map对象,map对象中放置所有被管理的对象。Spring中容器是指ApplicationContext接口及子接口或实现类。

beans:容器中所有被管理的对象称为beans。如果单说其中一个对象可称为bean。

●loC/DI的好处

Spring loC/DI使用后可以管理项目中相关对象,让对象管理的事情和业务分离(解耦)。同时也不管理对象的依赖关系,所有的依赖关系交给Spring容器进行管理。

●1oC/DI具体应用场景

1oC/DI主要作用就是管理对象的实例化和对象之间依赖关系。项目中以前需要自己实例化的层对象、需要自己实例化框架或工具包的入口类都可以交给Spring容器进行管理。

•层对象:PeopleMapper接口代理对象、PeopleDaolmpl、PeopleServicelmpl

•框架入口类:SqlSessionFactory等

下图中对应普通类PeopleMapper、PeopleServicelmpl这些不同层中普通都可以交给Spring容器进行管理。放入到容器中的对象可以相互直接依赖。但是Servlet只能被Tomcat管理(由Tomcat帮助实例化创建的),所以Spring容器是无法管理Servlet的。但是Servlet可以从Spring容器中取出对象。

四、第一个Spring项目

Spring框架不依赖于Servlet容器(Tomcat),所以普通Java项目就可以使用Spring框架。

Spring框架提供了XML、注解、Java Config三种方式进行使用。首先我们从XML方式开始学习。

●创建项目,并添加依赖 

创建普通Maven项目,并命名为spring1.

在项目的pom.xml中添加Spring项目的最基本依赖。

Spring项目想要运行起来必须包含:

• spring-context.jar。 spring上下文依赖,它依赖了下面的四个jar。

•spring-core.jar。Spring 核心jar包。它依赖了spring-jcl.jar

•spring-aop.jar。SpringAOP基本支持。

• spring-expression.jar。Spring的表达式语言支持。

•spring-beans.jar。Spring容器的bean管理。

•spring-jcl.jar。Spring 4版本时是common-logging.jar。从5开始Spring自己对日志进行了封装。

所以在Maven中想要使用Spring框架只需要在项目中导入spring-context就可以了,其他的jar包根据Maven依赖传递性都可以导入进来

●随意创建一个类

在项目下创建一个类作为测试Spring loC/DI功能的类。

五、Bean实例化的两种方式

在Spring中实例化Bean有两种方式:

•通过构造方法进行实例化。默认使用无参构造。这种方式和以前new的方式是等效的。上面的第一个Spring项目其实就是这种,只需要在XML中通过<bean>的class属性指定类的全限定路径,然后就可以实例化对象。

•通过工厂进行实例化。可以通过静态工厂和实例工厂进行实例化。这种方式完全是根据设计模式中工厂模式的思想而研发出的。Spring考虑到如果需要频繁实例化某个类的对象,工厂模式无疑是一个好选择。

第一个Spring项目已经演示过第一种实例化Bean的方式,所以下面重点演示使用工厂进行实例化bean。由于工厂模式又分为静态工厂和实例工厂两种方式,所以下面分成两部分进行演示。

●使用实例工厂实例化bean

•创建工厂类

实例工厂方式需要实例化工厂类。所以工厂中创建bean的方法是一个实例方法。

在项目中创建实例工厂类,并编写方法返回创建的实例对象。

示例中创建com.bjsxt.factory.PeopleFactory

●使用静态工厂实例化bean

• 创建工厂类

静态工厂和实例工厂类最主要的区别是,创建bean的方法是static修饰的。

创建静态工厂类:com.bjsxt.factory.PeopleStaticFactory

package com.bjsxt.factory;

●属性注入的三种方式/DI注入的三种方式/给对象中属性进行赋值的操作

•有参构造

<constructor-arg</constructor-arg>

•SET方法

<property></property>

•自动注入

在Spring中,允许Bean的自动注入。有两种方式进行配置。

•在根标签<beans>中配置default-autowire属性。标签整个Spring中自动注入的策略。可取值有5个。

default:默认值。不自动注入。

no:不自动注入。

byName:通过名称自动注入。会自动寻找容器中与当前属性同名的bean进行注入。

byType:通过类型自动注入。会自动寻找容器中与当前bean类型匹配的bean进行注入。如果有多个相同类型的bean注入会出现异常。

constructor:通过构造方法进行注入。写找bean的构造方法中是否有一个包含其他bean类型的参数。如果有自动注入进去。类型先byType后byName,如果没找到不注入。

注:构造方法类型和其Bean的类型相同。

•在<beany标签中配置autowire属性。和default-autowire取值相同。唯一注意default表示全局default-autowire的值。如果autowire和default-autowire同时存在,autowire生效。

自动注入指的都是bean之间的自动注入。能够自动注入必须保证Spring容器中包含能被自动注入的bean。

六、bean标签的scope属性

Spring中<bean>的scope控制的是Bean的有效范围。

●一共6个可取值:

singleton:默认值。bean是单例的,每次获取Bean都是同一个对象。

prototype:每次获取bean都重新实例化。

request:每次请求重新实例化对象,同一个请求中多次获取时单例的。

session:每个会话内bean是单例的。

application:整个应用程序对象内bean是单例的。

websocket:同一个websocket对象内对象是单例的。

里面的singleton和prototype在Spring最基本的环境中就可以使用,不需要web环境。

但是里面的request、session、application、websocket都只有在web环境才能使用。

●Spring中Bean是否是线程安全的?

如果bean的scope是单例的,bean不是线程安全的。

如果bean的scope是prototype,bean是线程安全的。

●Spring中Bean标签的Scope作用域

•在非web环境中可以使用

 singleton:默认值。bean是单例的,每次获取Bean都是同一个对象。

prototype:每次获取bean都重新实例化。 

•在web环境中可以使用

 request:每次请求重新实例化对象,同一个请求中多次获取时单例的。

 session:每个会话内bean是单例的。

application:整个应用程序对象内bean是单例的。

websocket:同一个websocket对象内对象是单例的。

七、单例设计模式

设计模式:根据面向对象五大设计思想衍生出的23中常见代码写法,每种写法可以专门解决一类问题。

单例设计模式:保证某个类在整个应用程序中只有一个对象。

单例写法分为两种:饿汉式、懒汉式。

●饿汉式

单例:希望类只有一个

核心思想:

1. 构造方法私有

2.对外提供一个能够获取对象的方法。

饿汉式:

优点:实现简单

缺点:无论是否使用当前类对象,加载类时一定会实例化。

●懒汉式

核心思想:

 1. 构造方法私有

2.对外提供一个能够获取对象的方法。

优点:

 按需创建对象。不会在加载类时直接实例化对象。

缺点:

写法相对复杂

 多线程环境下,第一次实例化对象效率低。

•不会立即实例化

•不是第一次访问的线程,直接通过if判断条件不成立。直接return

•防止多个线程已经执行到synchronized

八、Spring 循环注入问题

循环注入即多个类相互依赖,产生了一个闭环。

当两个类都是用构造注入时,没有等当前类实例化完成就需要注入另一个类,而另一个类没有实例化完整还需要注入当前类,所以这种情况是无法解决循环注入问题的的。会出现BeanCurrentlylnCreationException异常。

如果两个类都使用设值注入且scope为singleton的就不会出现问题,可以正常执行。因为单例默认下有三级缓存(DefaultSingletonBeanRegistry),可以暂时缓存没有被实例化完成的Bean。

但是如果两个类的scope都是prototype依然报BeanCurrentlylnCreationException。

九、BeanFactory和ApplicationContext

BeanFactory是Spring中的顶级接口,接口中定了Spring容器最基本功能。是Spring loC的最核心接口。

BeanFactory最常用实现类是XmlBeanFactory

无论是使用哪个写法,都可以发现BeanFactory是在真正getBean的时候才去实例化的。(可以通过添加输出语句,查看对象在什么时候实例化)

而ApplicationContext是BeanFactory的子接口。所以要比BeanFactory的功能更加强大,除了BeanFactory的功能,还包含了:

•AOP功能

•国际化(MessageSource)

•访问资源,如URL和文件(ResourceLoader)

•消息发送机制(ApplicationEventPublisher)

•Spring集成Web时的WebApplicationContext

          在使用时ApplicationContext时多使用ClassPathXmlApplicationContext

看出ApplicationContext是在加载文件后立即创建Bean。可以通过lazy-init属性进行控制,让bean懒加载

十、Spring整合web

Spring项目不需要依赖Web环境,但是Java项目大多数是Web项目,所以Spring也支持集成到Web环境中。

Spring 集成Web环境是通过Listener实现的,在ServletContext对象创建时加载Spring容器。Spring已经在spring-web.jar包中提供了ContextLoaderListener实现加载Spring配置文件的代码。我们只需要在web.xml配置<1istener>标签让ContextLoaderListener生效,并且告诉ContextLoaderListener加载Spring配置文件的路径即可。

●创建项目,并添加依赖

创建Maven的web项目(添加上webapp目录等,并配置web模块),并在pom.xml配置依赖。

十一、Spring支持的注解(IoC/DI相关)

@Repository、@Service、@Controller、@Configuration都是@Component注解的子注解,作用相同。主要的区别是语义上的区别。当看到不同的注解放在不同层的类中。但是不按照语义去做,非把@Service用在持久层,也是有效果的。但是这样却是不规范的。

@Component     实例化Bean,默认名称为类名收字母变小写。支持自定义名称

@Repository         @Component子标签。作用和@Component一样。用在持久层

@Service               @Component子标签。作用和@Component一样。用在业务层

@Controller           @Component子标签。作用和@Component一样。用在控制器层

@Configuration      @Component子标签。作用和@Component一样。用配置类

@Autowired          自动注入。默认byType,如果多个同类型bean,使用byName(默认通过属性名查找是否有同名的bean,也可以通过@Qualifier("bean名称"),执行需要注入的Bean名称)

@Resource            非Spring注解。默认byName,如果没找到,使用byType。

●DI:依赖注入

@Autowired (是Spring提供的)先按照类型进行注入 如果类型有多个再按照名称进行注入,如果同名的没有找到,就会按照@Qualifier()指定的名称进行注入

@Resource (非Spring提供):默认按照byName进行注入,如果没有找到再按照byType进行注入

注意:如果直接写到属性上进行注入 不需要写SET方法 因为底层使用反射直接给属性进行的注入所以不需要写SET方法

IOC/DI一定使用<context:component-scan base-package="com.bjsxt.pojo"</context:component-scan>进行扫描,如果有多个包需要使用逗号分割

●需求:实现计算器功能 有4个功能 加减乘除

功能设计完成后 可能过了5年时间 现在需要对之前的每一个操作添加一个日志记录功能,

日志输出格式为:第一个数:xx 第二个数为:xxx在xxx时间 做了xxx操作

解决方案:直接修改代码即可

弊端:

•过了N年可能源代码找不到了,因为运行的时候只要字节码文件

•如果代码可以修改你修改的前提是需要先梳理之前代码结果 然后再找对应的功能再做出修改,这个操作非常的麻烦

•即使可以修改源代码可能发生修改之后代码相互调用受到了影响

目的:在不修改源代码的前提下 从而实现功能的添加扩展

解决方案:AOP AOP的整体实现思想来源于设计模式动态代理 

●Aspect:切面。即join point + Advice

join point:切入点。就是我们平时说的目标方法,或说对哪个方法做扩展,做增强。

Advice:通知,增强内容。

Pointcut:切点。就是表达式,通过表达式说明哪些方法是join point

AOP Proxy:代理。Spring支持JDK动态代理和cglib动态代理两种方式,可以通过proxy-target-class=true把默认的JDK动态代理修改为Cglib动态代理。

Weaving:织入。织入就是把Advice添加到join point的过程。

在实际开发中AOP主要应用在Service层。

●AOP

AOP叫做面向切面编程,属于对OOP的扩展。其实现是基于动态代理设计模式,在loC基础上实现的。

AOP就是对某个切入点做了通知进行增强扩展,形成横切面。可以实现在不修改原有代码的情况下,做额外扩展。

 

十二、AspectJ实现AOP 

●AspectJ方式通知类型

•前置通知before

•后置通知:after是否出现异常都执行的后置通知。after-returning切入点不出现异常时才执行的后置通知

•环绕通知around

• 异常通知after-throwing

•创建通知类

Aspectj方式实现AOP的通知类不需要实现任何的接口,直接声明一个普通java类即可,然后在类中直接定义通知方法即可,方法名随意,但是建议方法名见名知意。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值