- IOC(依赖注入):一个bean依赖于另一个bean,Spring创建bean对象,注入另一个bean对象
a) 先导入Spring的核心jar包
b) 构造参数注入(在配置文件中配置注入)
i. 根据构造器参数的顺序注入
<!-- 按照索引注入,索引开始为0 -->
<bean id="MyBean" class="cn.itsource._01_.MyBean">
<constructor-arg index="0" value="666" />
<constructor-arg index="1" value="张二娃" />
</bean>
ii.
根据构造器参数的名称注入
<!-- 按照名称注入,名称必须一致 -->
<bean id="MyBean" class="cn.itsource._01_.MyBean">
<constructor-arg name="id" value="1" />
<constructor-arg name="name" value="张三娃" />
</bean>
iii.
根据构造器的类型注入
<!-- 按照类型注入,必须一一对应,不能有重复的类型-->
<bean id="MyBean" class="cn.itsource._01_.MyBean">
<constructor-arg type="java.lang.Long" value="1" />
<constructor-arg type="java.lang.String" value="张四娃" />
</bean>
iv. 构造参数时有个是我们的对象
- 在构造参数bean外面定义好我们自己对象给他一个id属性,构造时引用id值就行
- 在构造参数bean里面添加一个内部bean
c) 怎么配置一个Properties对象:配置连接池的时候经常用
i. 不支持中文
-
<property name="props1">
<value>
Jpa.dialect=org.Jpa.dialect.HSQLDialect
Jpa.driverClassName=com.mysql.jdbc.Driver
</value>
</property>
ii. 不支持中文
-
<property name="props2">
<props>
<prop key="Jpa.dialect">org.Jpa.dialect.HSQLDialect</prop>
<prop key="Jpa.driverClassName">com.mysql.jdbc.Driver中文 </prop>
</props>
</property>
- Xml自动注入方式
a) 通过名称自动注入
b) 通过类型自动注入
- 全注解自动注入
a)
先在xml配置文件里配置context命名空间约束条件
xmlns:context=http://www.springframework.org/schema/context
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
b)
配置让Spring扫描类和注解支持
<!-- 进行包的扫描,去看类上面是否有相应的标签配置 -->
<context:component-scan base-package="cn.itsource._03_anno(要扫描的包)"
/>
<!-- 这个不是必须的(spring3.2版本前使用) 配上后兼容性好 -->
<context:annotation-config />
c) 在类上面加上注解
d)
注解配置bean的名称
当一个接口有两个实现类时,Spring不知道用哪个实现类时,我们就在实现类上面打上@Repository(”自定义一个名称”)
e)
调用实现类的时候就除了打上@Autowired,再加@ Qualifier("实现类自定义的名称")
@Autowired和@resources作用是一样的
他们的区别:@Autowired 是Spring提供的注解、可以与Spring进行无缝连接,@Resources是java原生提供的注解
@Awtowired先根据类型匹配,匹配诶不上根据名称匹配
@Resources先根据名称匹配,匹配诶不上根据类型匹配
- XML手动注入,XML自动注入,注解自动注入,怎么选择?
初学使用xml版,手动注入
熟练之后可以使用xml自动注入现在趋势:注解版
如果是注解版,就全部使用注解(自己写类),不要混用,其它框架已经写好的类仍然使用xml进行配置
如果是xml版,在测试的使用必须使用注解注入(因为测试框架使用注解版)
只有自己写的类,才可以全部用注解,别人写的类使用注解必须去修改别人的源码,添加响应的注解标志
- AOP面向切面编程(业务功能的拓展)
a) 定义:是为了解决一些重复代码抽取问题,比如说我们在使用事务时有很多重复代码,但是又不能抽取到一个公共的类里面的这种情况。
b) AOP的一些术语
c) Spring的AOP功能
- 代理模式(通俗点就是中间商)
a) 静态代理(与现实生活不太符合实际,可能会有多个角色,就需要写多个构造方法)
- i. 三个角色:抽象角色,真实角色,代理角色
真实角色直接实现抽象角色,而代理角色要实现抽象角色,必须要通过构造方法传入真实角色才能实现。 - ii. 缺点:如果说有其他接口和方法,就需要写许多代理类
b) 动态代理
- i. 有接口的代理类:使用jdk的动态代理
- ii. 没有接口的代理类,使用CGLIB的动态代理模式,类不能由final修饰
c) 动态代理的实现
- i. 自定义一个代理类实现Invorcationhander接口,赋写invork方法,
- String实现AOP的两种方案(jdk和cglib)
a) 若目标对象实现了若干接口,就使用jdk动态代理
b) 若目标对象没有实现了若干接口,就使用cglib动态代理
注意:对接口创建代理要优于对类创建代理,降低系统的耦合,标记为final的方法不能被代理。
- XML版实现AOP
a) 添加aop的jar包
b) 添加命名xmlns:aop=http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
c) 直接使用环形增强
<bean id="txManager" class="cn.itsource.spring.transcational.TxManager"/>
<!--
环绕通知:有了环绕,就不需要用另外几个通知(会重复)
如果有两个以上的通知,建议使用环绕
-->
<aop:config>
<aop:pointcut expression="execution(* cn.itsource.spring.I*Service.*(..))" id="pointcut" />
<aop:aspect
ref="txManager">
<!--环绕通知-->
<aop:around
method="around"
pointcut-ref="pointcut"
/>
</aop:aspect>
</aop:config>
- 注解版实现AOP
一定要注意:无论是注解的方式还是xml配置方式配置事务,配置了环绕通知后一定不能再配置其他通知,两个同时配置的话会发生冲突,事务不会发生作用。
a) 配置文件中配置
<!-- 组件搜索 -->
<context:component-scan base-package="cn.itsource.spring" />
<!-- 支持aop注解 -->
<aop:aspectj-autoproxy />
b) 配置事务管理器和环绕通知方法
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.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect //AOP的类注解
public class TxManager {
//设置切点
@Pointcut("execution(* cn.itsource.aopanno.I*Service.*(..))")
public void pointcut(){}
//前置通知
@Before("pointcut()")
public void begin(){
System.out.println("开启事务....");
}
//后置通知
@AfterReturning("pointcut()")
public void commit(){
System.out.println("提交事务...");
}
//异常通知
@AfterThrowing(pointcut="pointcut()",throwing="e")
public void rollback(Throwable e){
System.out.println("回滚事务....");
System.out.println(e.getMessage());
}
//最终通知
@After("pointcut()")
public void close(){
System.out.println("关闭资源....");
}
}
环绕通知方法:
//温馨提醒:如果要使用环绕通知的话,把其它几个通知的注解去掉(不然会出现重复)
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint){
Object object = null;
try {
begin();
object = joinPoint.proceed(); //执行相应的代码
commit();
} catch (Throwable e) {
rollback(e);
}finally{
close();
}
return object;
10. 创建bean的方式
a) 实例化一个有公共无参构造的方法
b) 使用factoryBean接口创建bean
使用于在核心类里面没有提供构造方法的bean,创建方式:自定义一个类实现FactoryBean,然后在配置里面配置这个bean。
c) 面试题:说一下FactoryBean和BeanFactory的区别
- i. BeanFactory接口顶级父工厂,获取bean的实例
- ii. FactoryBean接口,不能通过默认的无参构造方法获取bean,需通过子类的getObject()返回实例。
- iii. 区别:BeanFactory可以直接实例化,FactoryBean不能实例化,需要通过实现类来获取对象
d) 集成静态简单工厂
- i. 自定义一个类,类里面定义一个获取实例的静态方法。
- ii. 配置文件里面配置该实例,和该方法
e) 集成实例简单工厂
- i. 自定义一个类,在类里面定义一个实例工厂的方法
配置文件配置该bean和方法