1,Spring框架介绍
IOC(控制反转):Spring容器帮我们管理对象(Bean Factory)
DI(依赖注入):Spring帮我们管理对象之间的依赖关系
AOP(面向切面编程):在不修改原代码的前提下,对项目进行升级和维护
2,IOC容器的bean特性
Bean的即时加载和懒加载
默认即时加载,IOC容器启动后就立即调用Bean的无参构造方法创建Bean实例
<bean id="sample1" class="com.bjpn.Sample"/>
<bean id="sample2" class="com.bjpn.Sample" lazy-init="default"/>
<bean id="sample3" class="com.bjpn.Sample" lazy-init="false"/>
延时加载又称懒加载,使用时才创建Bean实例
<bean id="sample" class="com.bjpn.Sample" lazy-init="true"/>
Bean实例默认是单例模式,一旦修改为多例模式加载方式会改为懒加载
<bean id="sample" class="com.bjpn.Sample" scope="singleton"/>
<bean id="sample" class="com.bjpn.Sample" scope="prototype"/>
Spring容器中Bean的生命周期
- 创建对象:默认在Spring容器启动时创建,为单例状态
- 属性注入:配置property
- 初始化:执行初始化方法
- 执行业务方法
- 销毁:执行销毁方法 (容器关闭时)
注入方式有
setter方法注入
构造器注入
自动装配
注解方式注入
3,AOP面向切面编程
1,设计模式
单例模式:保证项目中某个类的实例的唯一性
工厂模式:Spring的IOC就是Bean工厂
代理模式:proxy
2,代理模式的实现
1,静态代理
2,动态代理
1,使用JDK提供的Proxy创建代理对象
本质是产生接口的实现类作为代理类,所以目标类必须实现接口
public class JDKProxyFacotry implements InvocationHandler{
private Object target;//目标类
public Object createProxy(Object target){
this.target=target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
}
/*
proxy:代理对象
mehtod:目标方法
args:目标方法的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//增强功能
System.out.println("使用log4j写日志。。。。。");
//执行目标业务方法
return method.invoke(target,args);
}
}
public static void main( String[] args ){
JDKProxyFacotry facotry=new JDKProxyFacotry();
UserService userService=(UserService) facotry.createProxy(new UserServiceImpl());
userService.regist();
userService.login();
}
2,使用第三方的Cglib创建代理对象
本质是产生目标类的子类,不需要实现接口
public class StudentService {
public void show(){
System.out.println("显示学生。。。");
}
}
public class CglibProxyFactory implements MethodInterceptor {
private Object target;
public Object createProxy(Object target){
this.target=target;
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//增强功能
System.out.println("使用log4j写日志。。。。。");
return method.invoke(target,objects);
}
}
public static void main( String[] args ){
CglibProxyFactory facotry=new CglibProxyFactory();
StudentService service=(StudentService) facotry.createProxy(new UserServiceImpl());
service.show();
}
3,JDK动态代理和Cglib动态代理对比
1,JDK动态代理
使用JDK提供API工具类Proxy实现代理的,效率较高,要求目标类和代理类必须实现同一接口,其本质是通过Proxy在内存中动态产生业务接口的实现类作为代理对象。
2,Cglib动态代理
使用第三方的Cglib提供一种代理方式,该方式要求代理类继承目标类,通过重写目标类方法的形式来实现代理功能,该方式不需要目标类实现接口,但不能对final的类进行代理,其本质是在内存中动态产生目标类的子类作为代理对象的。
3,Spring框架的AOP同时采用了JDK和Cglib两种方式来实现代理,Spring根据需求不同而采用不同的代理方式,如果目标类实现类接口则会采用JDK的代理方式,反之就会采用Cglib的代理方式。
3,基于Spring的AOP实现
Aspect(切面):可以理解为需要增强的功能(辅助功能)的封装——类。
PointCut(切入点):对业务类中哪些方法进行拦截,如:* com.bjpn.service.*.*(..))
JoinPoint(连接点):所拦截方法的具体位置,如方法前、方法后、方法异常等
Advice(通知):拦截业务方法所做的事,通知分为:前置、后置、异常、最终、环绕通知
Target:目标对象
Weave(织入):将增强的功能和业务方法进行整合的过程称为织入
@Aspect
@Component
public class MyAspect {
@Pointcut("execution(* com.bjpn.service.*.*(..))")
void anyMethod(){}
//环绕通知
@Around("anyMethod()")
public Object doAround(ProceedingJoinPoint pjp){
Object result=null;
try {
System.out.println("前置通知");
result=pjp.proceed();//执行目标方法
System.out.println("后置通知");
} catch (Throwable e) {
System.out.println("异常通知");
}finally{
System.out.println("最终通知");
}
return null;
}
}