本教程對應視頻課程:http://edu.51cto.com/course/14731.htmlhtml
Autowired標籤的做用java
一、經過autowired標籤可讓spring自動的把屬性須要的對象從容器中找出來,並注入到對象spring
二、autowired標籤能夠放在字段或者setter方法上面框架
三、使用autowired標籤能夠注入一些spring內置的重要對象,好比BeanFactory,ApplicationContext;dom
四、默認狀況下,@Autowired標籤必需要能找到對應的對象,不然報錯;經過required=false來避免這個問題@Autowired(required=false)ide
五、第三方程序:spring3.0以前,須要手動配置@Autowired解析程序:spring就會自動的加入針對@Autowired標籤的解析程序<context:annotation-config />ui
六、@Autowired找bean的方式:this
①首先按照依賴對象的類型找;若是找到,就是用setter或者字段直接注入prototype
②若是在Spring上下文中找到多個匹配的類型,再按照名字去找;若是沒有匹配,報錯代理
③能夠經過使用@Qualifier("other")標籤來規定依賴對象按照bean的id+類型去找
@Resource標籤:
1.Resource標籤是JavaEE規範的標籤、
二、Resource標籤也能夠做用於字段或者setter方法
三、也能夠使用@Resource標籤注入一些spring內置的重要對象,好比BeanFactory.ApplicationContext
四、Resource必需要求有匹配的對象
五、Resource標籤找bean的方式
①首先按照名字去找,若是找到,就使用setter或者字段注入
②若是按照名字找不到,再按照類型去找,但若是找到多個匹配類型則會報錯
③能夠直接使用name屬性指定bean的名稱;可是,若是指定的name,就只能按照name去找,若是找不到,就不會再按照類型去找;
一、使用標籤來完成IoC,就必須有IoC標籤的解析器
使用context:component-scan來掃描spring須要管理的bean
base-package就告訴spring去哪些包及其子包裏去掃描bean,若是有多個包須要被掃描;只須要用逗號隔開多個包便可
<context:component-scan base-package="cn.org.kingdom.service,cn.org.kingdom.dao" />
二、標註Bean的註解:@Component
默認狀況,直接使用類的名字(首字母小寫做爲bean的名字), 若是要修改bean的名稱;直接使用value屬性來從新定義bean的名稱
@Component("otherbean")
public class OtherBean {}
三、使用@Component的限制:
①不能運用到靜態工廠方法和實例工廠方法,可是能夠使用到FactoryBean;
②對於沒有源代碼的類(框架內部的預約義類),只能用XML配置;
四、bean組件分類
@Service用於標註業務層組件
@Controller用於標註控制層組件(如struts中的action)
@Repository用於標註數據訪問組件,即DAO組件
@Component泛指組件,當組件很差歸類的時候,咱們能夠使用這個註解進行標註。
五、指定bean的做用域:@Scope("prototype")
六、初始化和銷燬方法
<bean init-method="init" />
@PostConstruct
public void init() {}
<bean destory-method="destory" />
@PreDestroy
public void destory() {}
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(); } }
一、代理對象徹底包含真實對象,客戶端使用的都是代理對象上面的方法,和真實對象無關;
二、靜態代理可以處理把不是真實對象該作的事情從真實對象上面撇開;
三、靜態代理帶來的問題:須要爲每個真實對象都得建立一個代理對象,致使類會急劇增長
/** 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方法中對要執行的方法名進行判斷
若一個類,沒有接口如何代理 ?
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中:
一、若目標對象實現了若干接口,spring就會使用JDK動態代理。
二、若目標對象沒有實現任何接口,spring就使用CGLIB庫生成目標對象的子類。對接口建立代理優於對類建立代理,由於會產生更加鬆耦合的系統。