概述及IOC配置
- 耦合
简单来说就是程序间的依赖关系
类间的依赖、方法间的依赖
- 解耦
降低程序间的依赖关系
比如:
1、在实际开发中应注意:在编译时不依赖,运行时才依赖(使用反射来创建对象而不使用new)
2.通过读取配置文件来获取要创建类的全限定名
使用工厂模式解耦,如何优化
通过分析dao操作发现很少需要能被修改的类成员,由此可得出,能使用单例优化。
实现方法如下
在需要获取相应对象的地方通过调用getbean方法即可得到
使用Spring
创建配置文件bean.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="accountService" class="com.jc.service.impl.AccountServiceImpl"></bean>
<bean id="accountDao" class="com.jc.dao.impl.AccountDaoImpl"></bean>
</beans>
测试
ApplicationContext的3种常用实现类
ClassPathXmlApplicationContext 配置文件必须在类路径下
FileSystemXmlAppilcationContext 需要有访问权限,位置为任意磁盘空间
AnnotationConfigApplicationContext 用于读取注解
核心容器的两个接口
1、ApplicationContext :在构建容器时,创建对象采用的是立即加载的策略,只要一读取完配置文件中的数据,立马就创建配置文件中的对象
2、BeanFactory:在构建容器时,创建对象采用延迟加载的方式,在用到相应对象时,才创建对象。
创建bean对象的3种方式
1、
2、
模拟spring如何通过注解扫描对象,同时给依赖的属性注入
public void testAnnotations2(){
Class<UserController> userControllerClass = UserController.class;
//获取描述类的注解(写在类的上面)
Annotation[] anns = userControllerClass.getDeclaredAnnotations();
for (Annotation ann : anns) {
System.out.println(ann);
}
//如果发现ioc扫描,spring就创建
//userControllerClass.newInstance();
//获取属性
Field[] fields = userControllerClass.getDeclaredFields();
//获取描述属性的注解
Annotation[] filedAnno = fields[0].getDeclaredAnnotations();
for (Annotation annotation : filedAnno) {
System.out.println(annotation);
}
//如果是依赖注入的注解,spring将帮助你注入
//若属性是私有的,则添加
fields[0].setAccessible(true);
//fields[0].set(实际的值);
}
3、
bean的作用范围
bean标签的scope属性,用来指定bean的作用范围,取值有(常用的就是单例和多例):
singleton 单例的(默认值)
prototype 多例的
request 作用于web应用的请求范围
session 作用于web应用的会话范围
global-session 作用于集群环境的会话范围(全局会话范围),当不是集群环境时,作用和session等同
bean对象生命周期
单例
多例,即使关闭了容器也不会销毁。只有当java垃圾回收才会。
spring依赖注入
依赖注入 Dependency Injection
IOC之作用:降低程序间的耦合(依赖关系)
将依赖关系的管理交给spring维护,在一个类中需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明依赖关系的维护就称为依赖注入.
注入方式
1.构造器
2.set
3.注解
可以注入的类型
1.基本类型和String
2.复杂类型/集合类型
3.在配置文件中配置过的bean类型
构造方法注入
- 优势:在获取对象时,必须注入参数,否则无法创建
- 弊端:改变了bean对象的实例化方式,使我们创建对象时,必须提供所有参数,如果用不到也需要提供。
set方法注入
复杂类型的注入
常用IOC注解
- 用于创建对象的注解
(@Controller:一般用在表现层 Service:一般用在业务层Repository:一般用在持久层,Component:其他层 四种功能,属性都一样)
在bean.xml中添加约束
告知去哪里扫描Component注解
添加注解 ,若不写value则在容器的map中key为类名且首字母小写
- 用于注入数据的
@Aotowired根据类型自动注入,根据容器中对象的类型自动注入。
只有容器中有且只有一个同类型对象才行,若容器中有两个或两个以上,根据变量名匹配相同的对象名称,一致则能注入,否则不能。
@Qualifier在按照类型注入的基础之上再按照名称注入,在给类成员注入时不能单独使用,但是作为方法参数时可以。
@Resource 注解 ,(属性为name,用于指定bean的id)
以上注解都只能注入其他类型的bean数据,基本类型、String都不能。另外,集合类型只能通过xml来注入。
@Value:(包含属性value,用来指定注入数据的值) 注入基本类型和String类型,同时可以使用SpEL(spring 的el表达式)。
- bean的作用范围的
@Scope指定bean的作用范围(属性和xml中一致,不写则为单例singleton)
生命周期
@PosConstruct指定初始化方法。
@PreDestory指定销毁方法。
Controller Service Dao
一般只有Contriller是非单例的,因为有许多成员变量,需要频繁的与前端进行交互。一般与前端进行交互的都是非单例的。
spring的AOP
AOP又称为面向切面编程。在java中有很多通用的功能(事务、异常、权限、日志)。这些通用功能并不是我们的核心功能,但是又必须要写,所以spring提出AOP,可以将这些通用功能和核心业务功能想分离.让开发者只关注业务本身.
好处:实现通用功能和原有的业务功能的解耦合扩展灵活,方便更新实现了通用功能的复用
6、AOP中的几个概念a.Aspect:切面,指定AOP中需要实现的通用功能
JoinPoint:切点,又叫连接点,指定切面组件再目标组件作用的位置
PointCut:切入点.指定那些方法需要被切入,相当于他是连接点的集合,一般会采用表达式的形式编写execution(* com.seecen.service..(…))描述的意思:任意返回值,指定包下所有的类所有的方法(参数任意)。
Advice:通知,指定切面组件再连接点上指定的动作和时机(什么时候切入)。有五种通知类型:前置通知,后置通知,异常通知,最后通知,环绕通知。
一般用于统计、事务、审计、性能监控、日志等、异常管理等等
使用:
定义一个切面(类)
在配置文件中进行配置
<!--声明切面-->
<bean id="logger" class="com.seecen.aop.Logger"></bean>
<!--aoc配置-->
<aop:config>
<!--描述那些方法需要被切入 (一个方法就是一个切点)-->
<aop:pointcut id="pc" expression=
"execution(* com.seecen.service.impl.*.*(..))"></aop:pointcut>
<!--配置切面-->
<aop:aspect id="aspect" ref="logger">
<!--配置前置通知
目标切入的方法之前执行
-->
<aop:before method="before" pointcut-ref="pc"></aop:before>
<!--配置后置通知
目标切入的方法之后执行,
returning 方法的返回值
-->
<aop:after-returning method="afterReturn" pointcut-ref="pc" returning="result"></aop:after-returning>
<!--配置异常通知
目标切入的方法运行时
-->
<aop:after-throwing method="afterThrow" pointcut-ref="pc" throwing="e"></aop:after-throwing>
<!--配置最后通知
try{
前置通知
int a = 1;
int b = 0;
int c = a/b;
后置通知
}catch(){
异常
}finally{
最后
}
-->
<aop:after method="after" pointcut-ref="pc"></aop:after>
</aop:aspect>
</aop:config>
最后通知是finally中的。并且在出现异常的时候前置通知和后置都不会执行,而是执行异常通知。
环绕通知(属于上述4种通知的集合)
通过注解实现
上述方法过于麻烦,可使用以下方法
需要在xml中配置
环绕通知
模拟记录日志
整合SSM
创建web工程,导入pom
创建spring、springmvc配置文件
创建mybatis配置文件,复制所需其他配置文件
web.xml配置
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--配置log4j-->
<!--定义一个参数-->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath*:log4j.properties</param-value>
</context-param>
<!--刷新时间-->
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>60000</param-value>
</context-param>
<!--指定spring配置文件的路径-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring.xml</param-value>
</context-param>
<!--配置springmvc处理乱码的过滤器-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--配置用于读取spring配置文件的监听器 (因为要在服务器启动时就读取配置文件
所以需要配置一个监听器来读取-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--配置springmvc核心servlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--指定配置文件的路径-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:springmvc.xml</param-value>
</init-param>
<!--设置服务器启动时初始化-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
关于报错ibatis.binding.BindingException: Invalid bound statement (not found)
关联映射文件出错,检查发现是能够跳转,不是关联的问题。检查target发现在打war包时没有将关联的映射文件打包(没有mapper文件夹)。
解决方法:
在pom.xml中修改配置