1:IOC:控制反转,不再把依赖对象交给应用本身创建和维护,而是交给外部容器创建和维护。这样控制权由应用转移到外部容器。
2:DI:依赖注入,在运行期,由外部容器动态的将依赖对象注入到组件中,可以通过构造函数的参数形式注入,也可以通过set方法注入。
3:为何要使用Spring
a.降低组件之间的耦合度,实现软件各层之间的解耦
Controller---Service---Dao
b.可以使用容器提供的各种服务,不需要处理复杂的事物传播行为
事务管理
c.容器提供单例模式,开发人员不需要自己编写实现代码
d.容器提供AOP技术,利用它很容易实现如权限拦截,运行期监控等功能。
e.容器提供了众多的辅佐类,使用这些类能够加快应用的开发,
如:jdbcTemplate、HibernateTemplate.
d.Spring对于主流的应用框架提供了集成支持,
如:集成hibernate、JPA、Structs 等,这样更便于应用的开发
4:轻量级与重量级概念的划分
主要看它使用了多少服务
如何使用spring?
使用spring需要的jar包
添加配置文件beans.xml,加入<bean id = "" class = "需要注入的类的路径"></bean>
ApplicationContext ctx =
new ClassPathXmlApplicationContext(String []{"beans.xml"})
ctx.getBean("配置文件中需注入类的class属性")
这样就可以得到我们所依赖的对象了,这个依赖对象由spring帮我们管理
Spring是如何读取beans.xml的?
Bean的作用域
scope=""
1.singleton 默认
容器实例化时对象被实例化,只创建一个对象
2.pototype
调用getBean()方法时被实例化,每次都会创建一个新对象
我们可以延迟实例化
在<bean>中加上 lazy-init = "true"
如果我们要将所有的bean都延迟实例化 就在<beans>中加入
default-lazy-init = "true"
如果需要当<bean>被实例化时就执行方法 就在<bean>中加入init-method = "方法名"
看一个对象是否被实例化,在他的默认构造方法中输出一句话 看看构造方法是否被调用
当我们需要关闭容器时执行某个方法,在bean中加入 destroy-method="方法名"
使用setter方法进行注入:
要将service层和dao层彻底解耦,我们需要将dao实现类所实现的接口直接注入到service
层,然后提供set、get方法,直接可以用注入的接口调用方法,在beans.xml中注入接口
的实现类,然后将它注入到service层的bean中作为属性,
<property name="personDao1" ref="personDao1" ></property>
name="属性名"
事实上是:先将PersonDaoBean注入到spring容器中,然后再将注入到spring容器中的
PersonDaoBean作为属性注入到PersonServiceBean中作为属性,命名为personDao,事实
上personDao本来就是PersonServiceBean的属性,所以啊,通过这么一来 就把
PersonDaoBean注入到PersonServiceBean中了 ,那么这时候PersonServiceBean
通过personDao就可以调用PersonDaoBean中的方法了。如此而已。 注意哦:这样注入就不要再提供带参构造方法了!!!
例子:
<bean id = "studentDao" class = "Student.Dao.Impl.StudentDaoImpl"></bean>
<bean id = "studentServiceBean" class = "Student.Service.StudentServiceBean">
<property name="studentDao" ref="studentDao"></property>
</bean>
还可以使用内部Bean方式为属性注入值,但不能被其他调用
像这样:
<property name="studentDao">
<bean class="Student.Dao.Impl.StudentDaoImpl"/>
</property>
注入基本类型:<property name="属性名" value="属性值"/> 定义一个变量,
然后生成get、set方法,
注入集合:
<property name="set">
<set>
<value>一</value>
<value>二</value>
<value>三</value>
</set>
</property>
<property name="list">
<list>
<value>一list</value>
<value>二list</value>
<value>三list</value>
</list>
</property>
<property name="map">
<map>
<entry key="key1" value="v1"></entry>
<entry key="key2" value="v2"></entry>
<entry key="key3" value="v3"></entry>
</map>
</property>
<property name="map1">
<map>
<entry key="key-map1" value="value-map1"></entry>
<entry key="key-map2" value="value-map2"></entry>
<entry key="key-map3" value="value-map3"></entry>
</map>
</property>
通过构造器注入值
<constructor-arg index="0" ref="personDao1"></constructor-arg>
<constructor-arg index="1" value = "sss"></constructor-arg>
index表示构造器参数的索引,从0开始
使用注解的方式注入依赖对象
@Autowired或者@Resource注解进行装配。但我们需要在xml配置文件中配置一下信息。
@Autowired:默认按类型进行装配
@Resource:默认按名称进行装配,名称找不到再按类型装配
@Resource
private PersonDao personDao1;
根据字段名称,到beans.xml中寻找名称相同的bean,然后将这个bean注入进来
如果找不到就会根据类型去找
不一定要注入在字段上,还可以注入到set方法上
当一个项目需要注入多个bean时,配置文件就会变的臃肿,因此在spring2.5的时候为我们提供
了<context:component-scan base-package="cn.itcast"></context:component-scan>
去自动扫描包下面的标注了注解@Service和@Repository和@component和@Controller
的类,并将这些类自动纳入spring容器中管理。同时可以为这些类指定作用域和名字哦,如:@Resource("name1") @Scope("pototype"),如果没有指定名称的话,这时候ctx.getBean("bean名称")中的bean名称就是类名称,但首字母小写
被@PostConstructs注解的方法是在Bean初始化时被调用的方法
被@PreDestory注解的方法是Bean实例被销毁之前调用该方法
AOP--切面
proxy代理类,只有是面向接口编程时 才能使用proxy代理类
目标对象必须要实现接口
代理对象实现了目标对象的所有方法,
使用cglib创建代理对象
springAOP
定义一个切面(基于注解):
/**
* 切面
*
*/
@Aspect
public class MyInterceptor {
@Pointcut("execution (* cn.itcast.service.impl.PersonServiceBean.*(..))")
private void anyMethod() {}//声明一个切入点 @Before("anyMethod() && args(name)")
public void doAccessCheck(String name) {
System.out.println("前置通知:"+ name);
}
@AfterReturning(pointcut="anyMethod()",returning="result")
public void doAfterReturning(String result) {
System.out.println("后置通知:"+ result);
}
@After("anyMethod()")
public void doAfter() {
System.out.println("最终通知");
}
@AfterThrowing(pointcut="anyMethod()",throwing="e")
public void doAfterThrowing(Exception e) {
System.out.println("例外通知:"+ e);
} @Around("anyMethod()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
//if(){//判断用户是否在权限
System.out.println("进入方法");
Object result = pjp.proceed();
System.out.println("退出方法");
//}
return result;
} }
定义一个切面(基于配置文件):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<aop:aspectj-autoproxy/>
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean>
<bean id="aspetbean" class="cn.itcast.service.MyInterceptor"/>
<aop:config>
<aop:aspect id="asp" ref="aspetbean">
<aop:pointcut id="mycut" expression="execution(* cn.itcast.service..*.*(..))"/>
<aop:before pointcut-ref="mycut" method="doAccessCheck"/>
<aop:after-returning pointcut-ref="mycut" method="doAfterReturning"/>
<aop:after-throwing pointcut-ref="mycut" method="doAfterThrowing"/>
<aop:after pointcut-ref="mycut" method="doAfter"/>
<aop:around pointcut-ref="mycut" method="doBasicProfiling"/>
</aop:aspect>
</aop:config>
</beans>
spring aop execution表达式说明
在使用spring框架配置AOP的时候,不管是通过XML配置文件还是注解的方式都需要定义pointcut"切入点" 例如定义切入点表达式 execution(* com.sample.service.impl..*.*(..)) execution()是最常用的切点函数,其语法如下所示: 整个表达式可以分为五个部分: 1、execution(): 表达式主体。 2、第一个*号:表示返回类型,*号表示所有的类型。 3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。 4、第二个*号:表示类名,*号表示所有的类。 5、*(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。