文章目录
静态代理动态代理
静态代理
静态代理:自己派生代理类.
代理类与被代理类是同类型的。代理类要持有被代理类。数据库连接池的简单实现,jdbc中Connection对象的close方法为关闭连接,使用连接池,通过代理设置,将close方法覆盖为归还Connection对象到池子里,而非直接关闭连接。
public class MyConnectionList {
private static LinkedList
<Connection> list
= new LinkedList<>();
public MyConnectionList(){
try {
Class
.forName("com.mysql.jdbc.Driver");
for(int i
=0;i
<10;i
++){
Connection connection
= DriverManager
.getConnection("jdbc:mysql://localhost:3306/704b?characterEncoding=utf8", "root", "root");
Connection connectionProxy
= new ConnectionProxy(connection
);
list
.add(connectionProxy
);
}
} catch (Exception e
) {
e
.printStackTrace();
}
}
public static void returnConnection(Connection conn
){
System
.out
.println("return begin-->currentSize:"+list
.size());
list
.add(conn
);
System
.out
.println("return end--> currentSize:"+list
.size());
}
public Connection
getConnection(){
System
.out
.println("currentSize:"+list
.size());
Connection connection
= list
.removeLast();
System
.out
.println("get--> currentSize:"+list
.size());
return connection
;
}
public void printInfo(){
System
.out
.println("total size:"+list
.size());
for (Connection conn
:list
){
System
.out
.println(conn
);
}
}
}
public class ConnectionProxy implements Connection {
private Connection source
;
public ConnectionProxy(Connection source
) {
this.source
= source
;
}
@Override
public void close() throws SQLException
{
System
.out
.println("-----------close------");
MyConnectionList
.returnConnection(this);
}
}
动态代理
自己不写代理类。在程序运行期间,动态的在虚拟机中生成代理类.
jdk:Proxy.要求被代理对象必须有接口(因为代理生成的$Proxy0对象已经继承了Proxy,java不支持多继承)第三方:cglib.被代理对象可以没有接口
public class MyConnectionList2 {
private static LinkedList
<Connection> list
= new LinkedList<>();
public MyConnectionList2(){
try {
Class
.forName("com.mysql.jdbc.Driver");
for(int i
=0;i
<10;i
++){
Connection connection
= DriverManager
.getConnection("jdbc:mysql://localhost:3306/704b?characterEncoding=utf8", "root", "root");
Connection connectionProxy
= getConnectionProxy(connection
);
list
.add(connectionProxy
);
}
} catch (Exception e
) {
e
.printStackTrace();
}
}
public Connection
getConnectionProxy(Connection source
){
ClassLoader classLoader
= source
.getClass().getClassLoader();
Class
[] interfaces
= new Class[]{Connection
.class};
InvocationHandler handler
= new InvocationHandler() {
@Override
public Object
invoke(Object proxy
, Method method
, Object
[] args
) throws Throwable
{
String name
= method
.getName();
if(name
.equals("close")){
MyConnectionList2
.returnConnection((Connection
) proxy
);
return null
;
}else
return method
.invoke(source
,args
);
}
};
Connection proxy
= (Connection
) Proxy
.newProxyInstance(classLoader
, interfaces
, handler
);
return proxy
;
}
public static void returnConnection(Connection conn
){
System
.out
.println("return begin-->currentSize:"+list
.size());
list
.add(conn
);
System
.out
.println("return end--> currentSize:"+list
.size());
}
public Connection
getConnection(){
System
.out
.println("currentSize:"+list
.size());
Connection connection
= list
.removeLast();
System
.out
.println("get--> currentSize:"+list
.size());
return connection
;
}
public void printInfo(){
System
.out
.println("total size:"+list
.size());
for (Connection conn
:list
){
System
.out
.println(conn
);
}
}
}
SqlSession.getMapper()的动态代理方式
public class TestGetMapper {
public static void main(String
[] args
) {
SqlSessionFactory factory
= SessionFactoryUtil
.get();
SqlSession session
= factory
.openSession();
SysuserMapper mapper
= getMapper(SysuserMapper
.class,session
);
Sysuser sysuser
= mapper
.selectUserByKey(1);
System
.out
.println(sysuser
);
}
public static <T> T
getMapper(Class
<T> clz
,SqlSession session
){
T t
= (T
)Proxy
.newProxyInstance(clz
.getClassLoader(), new Class[]{clz
}, new InvocationHandler() {
@Override
public Object
invoke(Object proxy
, Method method
, Object
[] args
) throws Throwable
{
String methodName
= method
.getName();
Class
<?> declaringClass
= method
.getDeclaringClass();
String name
= declaringClass
.getName();
String id
= name
+"."+methodName
;
MappedStatement mappedStatement
= session
.getConfiguration().getMappedStatement(id
);
SqlCommandType sqlCommandType
= mappedStatement
.getSqlCommandType();
if(sqlCommandType
==SqlCommandType
.SELECT
){
Class
<?> returnType
= method
.getReturnType();
if(Collection
.class.isAssignableFrom(returnType
)){
return session
.selectList(id
,args
[0]);
}else{
return session
.selectOne(id
,args
[0]);
}
}
return null
;
}
});
return t
;
}
}