什么是Spring
Spring是一款轻量级框架,可以解决企业开发的复杂问题,提供了web层-springMVC,业务层-ioc,持久层-jdbc的使用
Spring的好处
1.方便解耦
2.AOP编程
3.声明事物的支持
4.方便继承各种优秀的框架
Spring的属性
IOC控制反转
什么是控制反转呢,我们原来创建一个对象需要在代码里实现,现在我们依赖一个容器,把这些对象注入到我们的代码中,所以IOC也叫做依赖注入
spring提供了一个最基础的ioc容器,beanFactory,但这个容器是最顶层的文件夹,提供的功能较少,所以开发常用继承beanFactory的容器并扩展的applicationContext
我们要怎么加载这个容器呢?
在web.xml配置文件里,我们加上下面这行代码
<display-name>Archetype Created Web Application</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
AOP面向切面
AOP就是面向切面编程,原理就是用jdk动态代理或者cglib动态代理,但是jdk动态代理只能为接口创建代理实例,cglib采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截技术拦截所有父类的方法的调用并织入横切逻辑,所以一般用cglib
怎么使用
IOC注入,我们常用的注入方式有构造方法注入,set方法注入,注解方法注入
构造方法注入
<bean id="memberServiceImp" class="com.crc.serviceImp.MembersServiceImp">
<constructor-arg ref="memberDaoImp"></constructor-arg></bean>
<bean id="memberDaoImp" class="com.crc.daoImp.MembersDaoImp"></bean>
public class MembersServiceImp implements MembersService {
private MembersDaoImp memberDaoImp;
public MembersServiceImp(MembersDaoImp memberDaoImp) {
this.memberDaoImp = memberDaoImp;
}
}
上面这段代码意思就是把memberDaoImp对象通过构造方法注入到MembersServiceImp 服务代码中
set方法注入
<bean id="memberServiceImp" class="com.crc.serviceImp.MembersServiceImp">
<property name="memberDaoImp" ref="memberDaoImp"></property>
</bean>
<bean id="memberDaoImp" class="com.crc.daoImp.MembersDaoImp"></bean>
public class MembersServiceImp implements MembersService {
private MembersDaoImp memberDaoImp;
public void setMemberDaoImp(MembersDaoImp memberDaoImp) {
this.memberDaoImp = memberDaoImp;
}
}
上面这段代码意思就是把memberDaoImp对象通过set的方法注入到MembersServiceImp 服务代码中
构造方法和set方法区别在于配置bean中前者用的是constructor-arg ref=”memberDaoImp”,后者用的是property name=”memberDaoImp” ref=”memberDaoImp”
需要注意的是这两种方法不能在serviceImp代码上再加上@Service,否则会报错找到两个bean,ioc不知道识别哪一个的错误
注解方式注入
使用注解方式我们首先要加入扫描包代码,不用像构造方法和set方法再配置bean,这个扫描包的作用是自动搜寻定义的路径,当找到@Service和@Autowired就会自动注入对象
<context:component-scan base-package="com.crc.." />
@Service
public class MembersServiceImp implements MembersService {
@Autowired
private MembersDaoImp memberDaoImp;
}
上面注解的代码自动注入memberDaoImp
AOP面向切面编程
jdk动态代理主要涉及java.lang.reflect包中两个类,Proxy和InvocationHandler,InvocationHandle是一个接口,可以通过实现该接口定义横切逻辑
实现接口
package com.crc.utils;
public class FirstServiceImp implements FirstService {
public FirstServiceImp() {
// TODO Auto-generated constructor stub
}
@Override
public void one(int a) {
// TODO Auto-generated method stub
System.out.println("打印one:"+a);
}
@Override
public void two(int a) {
// TODO Auto-generated method stub
System.out.println("打印two:"+a);
}
}
实现InvacationHandler
public class PerformanceHandler implements InvocationHandler {
private Object target;
public PerformanceHandler(Object target) {
// TODO Auto-generated constructor stub
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
System.out.println("begin");
Object obj=method.invoke(target, args);
System.out.println("end");
return obj;
}
}
创建代理实例
public class FirstServiceTest {
@Test
public void proxy() {
FirstService target =new FirstServiceImp();
PerformanceHandler handler=new PerformanceHandler(target);
FirstService proxy =
(FirstService) Proxy.newProxyInstance(target.getClass().
getClassLoader(), target.getClass().getInterfaces(), handler);
proxy.one(10);
proxy.two(20);
}
@Test
public void test() {
fail("Not yet implemented");
}
}
打印结果
begin
打印one:10
end
begin
打印two:20
end
CGLIB动态代理
public class CglibProxy implements MethodInterceptor {
Enhancer enhancer = new Enhancer();
public CglibProxy() {
// TODO Auto-generated constructor stub
}
public Object getProxy(Class clazz){
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
// TODO Auto-generated method stub
System.out.println("begin");
Object obj=arg3.invokeSuper(arg0, arg2);
System.out.println("end");
return obj;
}
@Test
public void cglibProxy() {
CglibProxy target =new CglibProxy();
FirstServiceImp firstService=(FirstServiceImp) target.getProxy(FirstServiceImp.class);
firstService.one(10);
firstService.two(20);
}
打印结果
begin
打印one:10
end
begin
打印two:20
区别:
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
AOP在web常用的功能
事物管理
<!-- 配置tx声明事物配置 -->
<tx:advice id="advice" transaction-manager="transactionManager" >
<tx:attributes>
<tx:method name="insert" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="find" propagation="REQUIRED"/>
<tx:method name="queryForNum" propagation="REQUIRED"/>
<tx:method name="count" propagation="REQUIRED"/>
<tx:method name="queryForPage" propagation="REQUIRED"/>
<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor advice-ref="advice" pointcut="execution(* com.crc.serviceImp.*.*(..))"/>
</aop:config>