1、建立项目,导包(数据库驱动、Mybatis、Spring、Spring和Mybatis整合),配置文件(Spring主配置文件application_context.xml、数据库连接db.properties,日志系统log4j.properties);
2、配置数据源(spring主配置文件中要配置读取配置信息的工具)
<context:property-placeholder location="db.properties" />
3、dataSource→SQLSessionFactoryBean→sqlSessionTemplate→usersServiceImpl
4、SqlSessionDaoSupport的使用(内部有个成员属性sqlSessionFactory)
5、MapperScannerConfigurer,扫描某个包下的Mapper建立bean,不需要每个Mapper都配置bean。
<!--配置MapperScannerConfigurer的bean,会自动扫描basePackage属性值包内的所有对象
建立UserMapper的bean,供UsersServiceImpl3依赖注入使用 ! -->
<bean id="mapperScannerConfigurer"
class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.dyh.mapper" />
</bean>
<!--配置Service层的Bean,虽然本配置文件中没有配置usersMapper这个bean,但是
上面MapperScannerConfigurer已经扫描建立了一系列bean存在SpringIoC容器中-->
<bean id="usersService" class="com.dyh.service.impl.UsersServiceImpl3">
<property name="usersMapper" ref="usersMapper" />
</bean>
1、什么是代理模式
代理模式(Proxy Pattern):代理模式是 Java 常见的设计模式之一。所谓代理模式是指客户端并不直接调用实际的对象,而是通过调用代理对象,来间接的调用实际的对象。通俗的来讲代理模式就是我们生活中常见的中介。
2、为什么使用代理模式
隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
开闭原则:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。
2.1 代理模式的优点
代理模式能将代理对象与真实对象被调用的目标对象分离。
一定程度上降低了系统的耦合度,扩展性好。
保护目标对象。
增强目标对象。
2.2 代理模式的缺点
代理模式会造成系统设计中类的数目的增加。
在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。
增加了系统的复杂度。
3、代理模式的实现
代理模式可以分为两种:静态代理、动态代理。
3.1 静态代理
静态代理模式由三个部分构成:
一个公共的接口
一个被代理角色
一个代理角色
3.1.1 公共接口
接口:定义一种规范和标准,是共性行为的抽象。例如出租。
package staticproxy;
/**
* 出租 接口:行为规范
*/
public interface Rent {
void renting();
}
3.1.2 代理角色
隔壁老王有房要出租,实现出租接口。
package staticproxy;
/**
* 房东
*/
public class FangDong implements Rent{
@Override
public void renting() {
System.out.println("XXX小区XX室X厅 tel:xxxx");
}
}
3.1.3 代理角色
房屋中介,帮人代理租房。
package staticproxy;
/**
* staticproxy 静态代理 房屋中介
*/
public class StaticProxy implements Rent {
private Rent fangDong; // 委托者
public StaticProxy(Rent fangDong) {
this.fangDong = fangDong;
}
@Override
public void renting() {
System.out.println("带客户看房");
this.fangDong.renting(); // 委托者的出租要求
System.out.println("签订合同,收取租金,收取服务费");
}
}
3.1.4 创建测试类
package staticproxy;
/**
* 客户调用测试
*/
public class TestStaticProxy {
public static void main(String[] args) {
Rent fd = new FangDong(); // 委托者,实际房东
StaticProxy staticProxy = new StaticProxy(fd);// 房屋中介
staticProxy.renting();
}
}
运行结果:
3.2 动态代理的实现
在动态代理中分为两种实现方式:
使用 JDK 的 Proxy 类实现动态代理
使用 CGLIB 实现动态代理
3.2.1 使用 JDK 的 Proxy 类实现动态代理
3.2.1.1 创建业务接口
public interface JdkProxyRent {
void renting();
}
3.2.1.2 创建接口实现类
public class JdkProxyOldWang implements JdkProxyRent {
@Override
public void renting() {
System.out.println("OldWang 有房出租");
}
}
3.2.1.3 创建生成代理对象的工厂
public class JdkProxyFactory {
/**
* 动态生成代理对象
*/
public static Object getProxyBean(Object target){
Class clazz = target.getClass();
MyAspect myAspect = new MyAspect();
//在 JDK 中动态生成代理对象的方法
return Proxy.newProxyInstance(clazz.getClassLoader(),
clazz.getInterfaces(), new InvocationHandler() {
/**
* 动态生成代理对象中的方法。
* @param proxy 动态生成的代理对象
* @param method 目标方法的方法对象
* @param args 传递到目标方法中的参数列表
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[]
args) throws Throwable {
myAspect.before();
Object obj =
method.invoke(target,args);
myAspect.after();
return obj;
}
});
}
3.2.1.4 创建切面对象
public class MyAspect {
public void before(){
System.out.println("带领房客看房。。。签租房协议");
}
public void after(){
System.out.println("售后服务。");
}
}
3.2.1.5 创建测试类
public class JdkProxyTest {
public static void main(String[] args) {
JdkProxyRent jdkProxyRent = new JdkProxyOldWang();
JdkProxyRent jdkProxyRent1 = (JdkProxyRent)
JdkProxyFactory.getProxyBean(jdkProxyRent);
jdkProxyRent1.renting();
}
}
3.3.2 使用 CGLIB 实现动态代理
CGLIB(Code Generation Library)是一个高性能开源的代码生成包,它被许多框架所使用,其底层是通过使用一个小而快的字节码处理框架 ASM(Java 字节码操控框架)转换字节码并生成新的类。因此 CGLIB 要依赖于 ASM 的包。
JDK 的动态代理机制只能代理实现了接口的类,而对于没有实现接口的类就不能使用JDK 的 Proxy 类生成代理对象,cglib 是针对类来实现代理的,他的原理是对指定的目标类生成一个子类并通过回调的方式来实现增强,但因为采用的是继承,所以不能对 final 修饰的类进行代理。
3.3.2.1 添加 jar 包
cglib.jar
asm.jar
3.3.2.2 创建业务接口
public interface CglibProxyRent {
void renting();
}
3.3.2.3 创建接口实现类
public class CglibProxyOldwang implements CglibProxyRent {
@Override
public void renting() {
System.out.println("Oldwang 有房出租");
}
}
3.3.2.4 创建生成代理对象的工厂
public class CglibProxyBeanFactory {
public static Object getProxyBean(CglibProxyRent rent){
CglibMyAspect myAspect = new CglibMyAspect();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(rent.getClass());
enhancer.setCallback(new MethodInterceptor() {
/**
*
* @param o 代理对象的引用
* @param method 目标对象的方法对象
* @param objects 目标方法的参数列表
* @param methodProxy 目标方法的方法对象的代理对象
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[]
objects, MethodProxy methodProxy) throws Throwable {
myAspect.before();
Object obj = method.invoke(rent,objects);
myAspect.after();
return obj;
}
});
return enhancer.create();
}
}
3.3.2.5 创建切面
public class CglibMyAspect {
public void before(){
System.out.println("带领客户看房,签订租房协议");
}
public void after(){
System.out.println("售后服务");
}
}
3.3.2.6 创建测试类
public class Test {
public static void main(String[] args) {
CglibProxyRent rent = new CglibProxyOldlu();
CglibProxyRent rent1 = (CglibProxyRent)
CglibProxyBeanFactory.getProxyBean(rent);
rent1.renting();
}
}