博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring学习笔记(四)
阅读量:6572 次
发布时间:2019-06-24

本文共 6416 字,大约阅读时间需要 21 分钟。

本教程对应视频课程:

1、自动装配

1.1、Spring标签

Autowired标签的作用

1、通过autowired标签可以让spring自动的把属性需要的对象从容器中找出来,并注入到对象

2、autowired标签可以放在字段或者setter方法上面

3、使用autowired标签可以注入一些spring内置的重要对象,比如BeanFactory,ApplicationContext;

4、默认情况下,@Autowired标签必须要能找到对应的对象,否则报错;通过required=false来避免这个问题@Autowired(required=false)

5、第三方程序:spring3.0之前,需要手动配置@Autowired解析程序:spring就会自动的加入针对@Autowired标签的解析程序<context:annotation-config />

6、@Autowired找bean的方式:

​ ①首先按照依赖对象的类型找;如果找到,就是用setter或者字段直接注入

​ ②如果在Spring上下文中找到多个匹配的类型,再按照名字去找;如果没有匹配,报错

​ ③可以通过使用@Qualifier("other")标签来规定依赖对象按照bean的id+类型去找

1.2、J2EE标签

@Resource标签:

1.Resource标签是JavaEE规范的标签、

2、Resource标签也可以作用于字段或者setter方法

3、也可以使用@Resource标签注入一些spring内置的重要对象,比如BeanFactory.ApplicationContext

4、Resource必须要求有匹配的对象

5、Resource标签找bean的方式

​ ①首先按照名字去找,如果找到,就使用setter或者字段注入

​ ②如果按照名字找不到,再按照类型去找,但如果找到多个匹配类型则会报错

​ ③可以直接使用name属性指定bean的名称;但是,如果指定的name,就只能按照name去找,如果找不到,就不会再按照类型去找;

1.3、使用注解来化解配置

1、使用标签来完成IoC,就必须有IoC标签的解析器

​ 使用context:component-scan来扫描spring需要管理的bean

​ base-package就告诉spring去哪些包及其子包里去扫描bean,如果有多个包需要被扫描;只需要用逗号隔开多个包即可

​ <context:component-scan base-package="cn.org.kingdom.service,cn.org.kingdom.dao" />

2、标注Bean的注解:@Component

默认情况,直接使用类的名字(首字母小写作为bean的名字), 如果要修改bean的名称;直接使用value属性来重新定义bean的名称

@Component("otherbean")

public class OtherBean {}

3、使用@Component的限制:

①不能运用到静态工厂方法和实例工厂方法,但是可以使用到FactoryBean;

②对于没有源代码的类(框架内部的预定义类),只能用XML配置;

4、bean组件分类

@Service用于标注业务层组件

@Controller用于标注控制层组件(如struts中的action)

@Repository用于标注数据访问组件,即DAO组件

@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

5、指定bean的作用域:@Scope("prototype")

6、初始化和销毁方法

@PostConstruct

public void init() {}

@PreDestroy

public void destory() {}

1、动态代理

1.1、静态代理回顾

1.1.1、模型图

mark

1.1.2、代码实现

package cn.org.kingdom.proxy;interface Subject{    public void getMoney();}class RealSubject implements Subject{    @Override    public void getMoney() {        System.out.println("求求你,能不能还我钱");    }}class Proxy implements Subject{    private Subject subject;    public Subject getSubject() {        return subject;    }    public void setSubject(Subject subject) {        this.subject = subject;    }    public void preGetMoney(){        System.out.println("带上大砍刀");    }    @Override    public void getMoney() {        preGetMoney();        subject.getMoney();        afterGetMoney();    }    public void afterGetMoney(){        System.out.println("赔偿精神损失费,拿去佣金");    }}public class ProxyTest {    public static void main(String[] args) {        RealSubject real = new RealSubject() ;         Proxy p = new Proxy();        p.setSubject(real);        p.getMoney();    }}

1.1.3、静态代理

1、代理对象完全包含真实对象,客户端使用的都是代理对象上面的方法,和真实对象无关;

2、静态代理能够处理把不是真实对象该做的事情从真实对象上面撇开;

3、静态代理带来的问题:需要为每一个真实对象都得创建一个代理对象,导致类会急剧增加

1.2、动态代理

1.2.1、jdk的动态代理

/**    ClassLoader loader:类加载器    Class
[] interfaces:要实现的接口 InvocationHandler h:调用处理器 return :代理对象*/public static Object newProxyInstance(ClassLoader loader, Class
[] interfaces,InvocationHandler h){}/** proxy:生成的代理对象 method:当前调用的真实方法 args: 当前调用方法的实参 return : 真实方法的返回结果*/public Object invoke(Object proxy, Method method, Object[] args) {}

参考代码

package cn.org.kingdom.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import cn.org.kingdom.ts.Transation;public class MyinvocationHanlder implements InvocationHandler {    //真实角色    private Object obj ;  //obj必须实现接口(jdk原生动态代理)    //ts附加功能对象    private Transation ts ;     public MyinvocationHanlder() {        super();    }    public MyinvocationHanlder(Object obj, Transation ts) {        super();        this.obj = obj;        this.ts = ts;    }    public Object getObj() {        return obj;    }    public void setObj(Object obj) {        this.obj = obj;    }    public Transation getTs() {        return ts;    }    public void setTs(Transation ts) {        this.ts = ts;    }    public Object getProxy(){        return                 Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);    }    @Override    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        Object value = null ;         if(obj.getClass().getName().endsWith("ServiceImpl")){            if("add".equals(method.getName())||"insert".equals(method.getName())) {                //aop要植入的操作                try{                    ts.begin();                    value= method.invoke(obj, args);                    int c= 10/0;                    ts.commit();                }catch(Exception e)  {                    ts.rollback();                }                return value;            }else{                method.invoke(obj, args);            }        }           return null;    }}

JDK动态代理

①代理的对象必须要实现一个接口;

②需要为每个对象创建代理对象;

③动态代理的最小单位是类(所有类中的方法都会被处理);

JDK动态代理总结

①JAVA动态代理是使用java.lang.reflect包中的Proxy类与InvocationHandler接口这两个来完成的。

②要使用JDK动态代理,必须要定义接口。

③JDK动态代理将会拦截所有pubic的方法(因为只能调用接口中定义的方法),这样即使在接口中增加了新的方法,不用修改代码也会被拦截。

④如果只想拦截一部分方法,可以在invoke方法中对要执行的方法名进行判断

1.2.2、CGLIB动态代理

若一个类,没有接口如何代理 ?

javassist.jar:Struts2的代理实现方案.

cglib.jar:Spring的代理实现方案

java类实现

public class TransactionCallback implements org.springframework.cglib.proxy.InvocationHandler {    private Object target;//真实对象    private TransactionManager txManager;    //不需要事务的方法    private String[] methodNames = { "update", "get" };    public TransactionCallback(Object target, TransactionManager txManager) {        this.target = target;        this.txManager = txManager;    }    //创建代理对象    public Object getProxyInstance() {        Enhancer enhancer = new Enhancer();        enhancer.setClassLoader(this.getClass().getClassLoader());        enhancer.setSuperclass(target.getClass());        enhancer.setCallback(this);        return enhancer.create();    }    public Object invoke(Object proxy, Method method, Object[] args){        Object ret = null;        if(Arrays.asList(methodNames).contains(method.getName())){            method.invoke(target, args);            return null;        }        txManager.beginTransaction();        try {            method.invoke(target, args);            txManager.commint();        } catch (Exception e) {            txManager.rollback();        }        return ret;    }}

总结:

CGLIB代理总结:

①CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。

②要求类不能是final的,要拦截的方法要是非final、非static、非private的。

③动态代理的最小单位是类(所有类中的方法都会被处理);

代理总结:

Spring中:

1、若目标对象实现了若干接口,spring就会使用JDK动态代理。

2、若目标对象没有实现任何接口,spring就使用CGLIB库生成目标对象的子类。对接口创建代理优于对类创建代理,因为会产生更加松耦合的系统。

转载于:https://blog.51cto.com/11230344/2287873

你可能感兴趣的文章
存储过程和SQL语句比较及存储过程在C#中调用方法
查看>>
hihocoder 1014 Trie树
查看>>
ADO.NET笔记——使用DataSet返回数据
查看>>
【机器学习】--关联规则算法从初识到应用
查看>>
windows 下nginx php安装
查看>>
MOTO XT702添加开机音乐
查看>>
Codeforces Round #565 (Div. 3) C. Lose it!
查看>>
Python脚本日志系统
查看>>
Spring异常——BeanNotOfRequiredTypeException
查看>>
B0BO TFS 安装指南(转载)
查看>>
gulp常用命令
查看>>
TCP(Socket基础编程)
查看>>
RowSet的使用
查看>>
表单提交中的input、button、submit的区别
查看>>
每日一记--cookie
查看>>
约瑟夫环
查看>>
S5:桥接模式 Bridge
查看>>
线程池-Executors
查看>>
WPF and Silverlight 学习笔记(十二):WPF Panel内容模型、Decorator内容模型及其他...
查看>>
FLUSH TABLES WITH READ LOCK 和 LOCK TABLES比较
查看>>