代理模式

首先,新建一个service包,作为业务层,业务层新建代码UserService
package com.lr.spring.service;
public interface UserService {
void insert();
}
再新建一个staticProxy(静态的代理服务器)包,写UserService的实现类放在staticProxy包里
1.代码逻辑
目标对象
package com.lr.spring.staticProxy;
import com.lr.spring.service.UserService;
//目标对象
public class UserServiceImpl implements UserService {
@Override
public void insert() {
System.out.println("目标对象的方法:插入一个User对象");
}
}
代理对象
package com.lr.spring.staticProxy;
import com.lr.spring.service.UserService;
//代理对象
public class UserServiceProxy implements UserService {
//1.注入目标对象,底层我们依然需要去调用目标对象中接口的方法
private UserService userService;
//构造方法
public UserServiceProxy(UserService userService) {
this.userService = userService;
}
//2.需要对目标对象的特定方法进行增强(加上事务),调用目标对象的方法
@Override
public void insert() {
try{
System.out.println("开启事务");
userService.insert();//调用目标对象的方法
System.out.println("提交事务");
}catch (Exception e){
System.out.println("回滚事务");
}finally {
System.out.println("最终操作");
}
}
}
测试目标对象与代理对象
@Test
public void test01() {
//目标对象
UserService userService = new UserServiceImpl();
userService.insert();
System.out.println("..................");
//代理对象
UserServiceProxy userServiceProxy = new UserServiceProxy(userService);
userServiceProxy.insert();
}
面向切面编程思想
静态代理
.静态代理:代理类由程序员自己编写(代理类会对目标对象的特定方法进行增强)
1)设计接口
原因:代理对象和目标对象都实现同一个功能,比如谦哥,中介都进行租房。
2)编写目标对象(类):实现接口
3)编写代理对象(类):实现接口,注入目标对象,调用其方法,最后增强方法。
缺点:每次编写一个目标类的时候,都需要重新去编写(至少)一个代理类,太麻烦了,我们希望由系统帮咱们生成代理对象。
1.新建一个TranAop切面类,把固有的几种操作封装起来
package com.lr.spring.Aop;
public class TranAop {
public void before(){
System.out.println("开启事务");
}
public void after(){
System.out.println("提交事务");
}
public void exception(){
System.out.println("回滚事务");
}
public void myFinally(){
System.out.println("最终的操作");
}
}
2.实现类
package com.lr.spring.staticProxy;
import com.lr.spring.Aop.TranAop;
import com.lr.spring.service.UserService;
public class UserServiceProxyAopImpl implements UserService {
public UserService userService;
public TranAop tranAop;
public UserServiceProxyAopImpl(UserService userService, TranAop tranAop) {
this.userService = userService;
this.tranAop = tranAop;
}
@Override
public void insert() {
try{
tranAop.before();
userService.insert();//调用目标对象的方法
tranAop.after();
}catch (Exception e){
tranAop.exception();
}finally {
tranAop.myFinally();
}
}
}
3.测试结果
@Test
public void test02(){
TranAop aop=new TranAop();
UserServiceImpl userService=new UserServiceImpl();
UserServiceProxyAopImpl userServiceProxyAop=new UserServiceProxyAopImpl(userService,aop);
userServiceProxyAop.insert();
}
动态代理
1.常见问题
1.什么是动态代理?
程序运行的时候,根据要被代理分对象动态生成代理类
代理类不需要程序员自己去编写,由系统提供,我们只需要关注业务方法的功能增强(处理)
2.动态代理的分类:
jdk动态代理和cglib动态代理。
3.jdk动态代理(重点)和cglib动态代理有什么区别?
1.jdk动态代理
(1).要求目标对象必须实现接口
(2).Proxy(代理类) public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h){ }
该方法可以为任何实现了接口的对象提供代理对象,而且可以针对目标对象实现的接口中的方法进行增强
参数ClassLoader loade(类加载器)
参数Class<?>[] interfaces:目标对象接口的实现(为什么用数组?可以多实现)
参数InvocationHandler h:回调,接口,处理(增强)目标对象接口中的方法。
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;//自己需要编写的部分
}
method指代理目标对象接口中的方法,使用的时候,往往method.inveke(目标对象,参数)
(3).Method public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { }
功能:调用当前对象的方法,obj:对象。args:参数
2.cglib动态代理:
cglib代理生成目标对象的子类对象(底层在内存中生成了该目标对象的子类对象),会对目标对象中所有的方法都进行增强(处理)
cglib代理被称为子类代理
1.特点:目标对象不需要实现接口,就可以提供其代理对象
注意:对特殊方法(final),无法处理。
2.hibernate和spring底层广泛使用到了cglib代理,但是面试的时候一般问jdk为主。
3.核心方法
Enhancer:核心类,提供目标对象的子类对象
create():静态方法,提供代理对象,等价于Proxy的newProxyInstance MethodInterceptor接口
intercept:抽象方法,对目标对象方法的增强
2.代码实现
1.UserService
package com.lr.spring.service;
public interface UserService {
void undateUser();
void inserUser(String name);
String findUserById(int id);
}
目标对象实现类
package com.lr.spring.service;
//目标对象(类)
public class UserServiceImpl implements UserService {
@Override
public void undateUser() {
System.out.println("修改操作");
}
@Override
public void inserUser(String name) {
System.out.println("插入操作:"+name);
}
@Override
public String findUserById(int id) {
System.out.println("查询操作,根据id"+id+"进行查询");
return "user:"+id;
}
}
测试自动生成代理对象
package com.lr.spring;
import com.lr.spring.service.UserService;
import com.lr.spring.service.UserServiceImpl;
import org.junit.Test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class AppTest {
@Test
public void test01() {
//在回调中使用外接的对象,该对象需要使用final修饰
final UserService userService = new UserServiceImpl();
//自动生成代理类的方法
UserService userService2 = (UserService)Proxy.newProxyInstance(
userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(userService, args);// 调用目标对象的底层(接口中的)方法
return result;
}
}
);
System.out.println(userService2.getClass());
String user = userService2.findUserById(100);
System.out.println(user);
userService2.undateUser();
userService2.inserUser("龙仁");
}
}
此刻还没有对目标对象的方法进行增强
测试对目标对象的方法增强
package com.lr.spring;
import com.lr.spring.service.UserService;
import com.lr.spring.service.UserServiceImpl;
import org.junit.Test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class AppTest {
@Test
public void test01() {
//在回调中使用外接的对象,该对象需要使用final修饰
final UserService userService = new UserServiceImpl();
//自动生成代理类的方法
UserService userService2 = (UserService)Proxy.newProxyInstance(
userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法名中以find开头的方法,都不加人事务管理
if(method.getName().startsWith("find")){
Object obj = method.invoke(userService,args);
return obj;
}else{
try {
System.out.println("开启事务");
Object result = method.invoke(userService, args);// 调用目标对象的底层(接口中的)方法
System.out.println("提交事务");
return result;
} catch (Exception e) {
System.out.println("回滚事务");
throw e;//这里尽量不要用return null,否则放在真实环境中会报空指针异常
}finally {
System.out.println("最终结果");
}
}
}
}
);
System.out.println(userService2.getClass());
String user = userService2.findUserById(100);
System.out.println(user);
userService2.undateUser();
userService2.inserUser("龙仁");
}
}
3.使用工厂模式对其封装
1.新建切面类,封装方法
package com.lr.spring.aop;
public class TranAop {
public void before(){
System.out.println("开启事务");
}
public void after(){
System.out.println("提交事务");
}
public void exception(){
System.out.println("回滚事务");
}
public void myFinally(){
System.out.println("最终的操作");
}
}
2.新建工厂类,封装方法
package com.lr.spring.jdkProxy;
import com.lr.spring.aop.TranAop;
import com.lr.spring.service.UserService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxyFactory {
//属性:目标对象(接口),切面类TranAop
private UserService userService;
private TranAop aop;
public JdkProxyFactory(UserService userService, TranAop aop) {
this.userService = userService;
this.aop = aop;
}
//工厂方法:提供代理对象
public Object getProxyInstance(){
return Proxy.newProxyInstance(userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;//标记思想
if (method.getName().startsWith("find")){
method.invoke(userService,args);
}else{
try{
aop.before();
Object obj = method.invoke(userService,args);
aop.after();
return obj;
}catch (Exception e){
aop.exception();
throw e;
}finally {
aop.myFinally();
}
}
return result;
}
});
}
}
3.测试程序
@Test
public void test02() {
UserService userService = (UserService) new JdkProxyFactory(new UserServiceImpl(), new TranAop()).getProxyInstance();
userService.inserUser("龙仁");
userService.undateUser();
userService.findUserById(100);
}
4.子类代理
1.创建目标对象/类
package com.lr.spring.service;
//目标对象
public class EmpService {
public void updateEmp(String name){
System.out.println("修改操作");
}
public void deleteEmo(int id){
System.out.println("删除对象");
}
}
2.直接进行测试(不需要实现任何接口)
@Test
public void test03(){
EmpService empService=new EmpService();
EmpService empService2= (EmpService) Enhancer.create(empService.getClass(),
new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("目标对象方法的增强");
Object result = methodProxy.invokeSuper(o,objects);//调用目标对象底层方法
return result;
}
});
System.out.println(empService2);
//验证底层方法是否实现
empService2.updateEmp("龙仁");
empService2.deleteEmo(100);
}
3.使用切面类进行封装
public void test03(){
EmpService empService=new EmpService();//目标对象
EmpService empService2= (EmpService) Enhancer.create(empService.getClass(),
new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
try{
System.out.println("开启事务");
Object result = methodProxy.invokeSuper(o,objects);//调用目标对象底层方法
System.out.println("提交事务");
return result;
}catch (Exception e){
System.out.println("回滚事务");
throw e;
}finally {
System.out.println("最终结果");
}
}
});
System.out.println(empService2);
//验证底层方法是否实现
empService2.updateEmp("龙仁");
empService2.deleteEmo(100);
}
4.使用工厂模式
public Object geiProxyIntance(){
return Enhancer.create(empService.getClass(),
new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
try{
tranAop.before();
Object result = methodProxy.invokeSuper(o, objects);
tranAop.after();
return result;
}catch (Exception e){
tranAop.exception();
throw e;
}finally {
tranAop.myFinally();
}
}
});
}
测试程序
@Test
public void test04(){
TranAop aop=new TranAop();
EmpService empService=new EmpService();
EmpService empService2= (EmpService)new CglibProxyFactory(empService,aop).geiProxyIntance();
empService2.updateEmp("龙傲天");
empService2.deleteEmo(3);
}
}