1. 程式人生 > >spring學習2

spring學習2

ace 自動 動態 prototype code target 推薦 作用 @override

使用註解配置spring

步驟:

1. 導包4(core/bean/context/spel)+1(logging)+spring-aop包(新版spring需要導入這個包)

2. 為主配置文件引入新的命名空間(約束) Context約束

3. 開啟使用註解代理配置文件

<context:component-scan base-package="com.domain">  指定掃描 com.domain包下面所有類的註解(同時會掃描子包裏面的類)

4. 在類中使用註解完成配置

@Component("user")public class User {
    
private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override
public String toString() { return "User [name=" + name + ", age=" + age + ", car=" + car + "]"; } }

將對象註冊到容器

@Component(“user”)

@Service(“user”) service層

@Controller(“user”) web層

@Repository(“user”) dao層

本質上這四個功能都是一樣 只是為了見名知意

修改對象的作用範圍

@Scope(scopeName=”prototype”) 指定對象的作用範圍 同樣也是作用在實體上面

值類型註入

@Value("tom")
private String name;

通過反射來為Field賦值 ,但是這樣破壞了封裝性

通過set方法來賦值 推薦使用

@Value("24")
public void setAge(Integer age) {
    this.age = age;
}

引用類型註入

1.使用AutoWired 自動裝配

@Component("user")
public class User {
    @Autowired
    private Car car;

        setCar/getCar ...
}

@Component
class Car{
    private String cName;
    private String color;
get/set ... } 註意:使用自動裝配,被裝配的字段 也要在容器有 可以沒有名字

這種方式有一個壞處:如果匹配多個類型一致的對象,將無法選擇具體註入哪一個對象

解決辦法:使用 Qualifier("car") 通過該註解來告訴 spring容器自動裝配哪個名稱的對象

註意:Qualifier和AutoWired要一起使用

@Resource(name="car") 手動註入,指定註入哪個名稱的對象

@Resource(name="car")
private Car car;

初始化 | 銷毀方法

@PostConstruct                      // 在對象被創建以後調用   相當於配置文件中定義的init-method 
public void init() {
    System.out.println("init method");
}
    
@PreDestroy                       // 在對象被銷毀前調用        destory-method
public void destory(){
    System.out.println("destory method");
}                                                

spring與junit整合測試

1.導包 4+2+aop+test

2.配置註解

@RunWith(SpringJUnit4ClassRunner.class)      // 幫我們創建容器
@ContextConfiguration("classpath:applicationContext.xml")  //指定創建容器時使用的配置文件
public class Student {
    
    @Value("wanglei")
    private String name;
    
    @Test
    public void test() {
        System.out.println(name);
    }
    
    @Value("24")
    private Integer age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}

spring中的aop

aop思想介紹 橫向重復代碼 ,縱向抽取

例如:解決亂碼問題 管理事務 action攔截器

spring中的aop概念 ------> spring能夠為容器中管理的對象生成動態代理對象

以前我們要使用動態代理,需要自己調用下面的方法

Proxy.newProxyInstance(xx,xx,xx) 生成代理對象

現在spring能夠幫助我們生成代理對象

spring實現aop的原理

1.動態代理(優先) : 被代理對象必須要實現接口,才能產生代理對象,如果沒有接口將不能使用動態代理技術。

2.cglib代理(沒有接口) : 第三方代理技術,cglib代理可以對任何類生成代理,代理的原理是對目標對象進行繼承代理.

但是如果目標對象被final修飾,那麽該類無法被cglib代理.

步驟:

1.創建service的接口是實現類

public interface UserService {
    void save();
    void add();
    void delete();
    void find();
}

public class UserServiceIml implements UserService {
    public void save() {
        System.out.println("save");
    }
    public void add() {
        System.out.println("add");
    }
    public void delete() {
        System.out.println("delete");
    }
    public void find() {
        System.out.println("find");
    }
}

2.使用cglib代理生成代理對象

public class Test implements MethodInterceptor{
    
    public UserService getService() {
        Enhancer en=new Enhancer();   //用於生成代理對象
        en.setSuperclass(UserServiceIml.class);//對誰設置代理
        en.setCallback(this); //代理要做什麽
        UserService service = (UserService) en.create();//創建代理對象
        return service;
    }
    
    @Override           proxyObj 目標類的實例  method 目標類方法的反射實例   arg 參數  methodProxy 代理類實例            
    public Object intercept(Object proxyObj, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
        System.out.println("打開事務!");
        Object returnValue = methodProxy.invokeSuper(proxyObj, arg);
        System.out.println("提交事務!");
        return returnValue;
    }    
}

3.測試

public static void main(String[] args) {
        Test test = new Test();
        UserService service = test.getService();
        service.save();
}

AOP名詞學習

Joinpoint(連接點):目標對象中,所有可以增強的方法

Pointcut(切入點): 目標對象,已經增強的方法

Advice(通知/增強):增強的代碼

Target(目標對象): 被代理的對象

Weaving(織入):將通知應用到切入點的過程

Proxy(代理):將通知織入到目標對象之後,形成代理對象

Aspect(切面):切入點 + 通知

spring中的aop演示

步驟:

1.導包4(core + bean + spel + context)+2 + 2(aop + aspect) + 2(allowiance + weaving)

aop包 + aspect包 + aopalliance + weaver

技術分享圖片

2.準備目標對象

技術分享圖片

3.準備通知

前置通知 目標方法運行之前調用

後置通知(如果出現異常不會調用) 在目標方法運行之後調用

環繞通知 在目標方法之前和之後都調用

異常攔截通知:如果出現異常,就會調用

後置通知(無論是否出現異常都會調用) :在目標方法運行之後調用

public class MyAdvice {
    //前置通知
    public void before() {
        System.out.println("前置通知");
    }
    //後置通知
    public void afterReturn() {
        System.out.println("後置通知(如果出現異常不會被調用)");
    }
    //環繞通知
    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("這是環繞通知之前的部分");
        Object proceed = pjp.proceed();//調用目標方法
        System.out.println("這是環繞通知之後的部分");
        return proceed;
    }
    //異常攔截通知
    public void afterException() {
        System.out.println("出現異常了");
    }
    //後置通知
    public void after() {
        System.out.println("後置通知(出現異常也會調用)");
    }
}

4.配置進行織入,將通知織入目標對象中

準備工作:導入AOP(約束)命名空間

1.配置目標對象 將具體的實現類(而不是接口添加進來) 因為是為 實現類來創建代理對象

<bean name="userService" class="..."></bean>

2.配置通知對象

<bean name="myAdvice" class="...">

3.配置切入點

<aop:pointcut expression="execution(* cn.itcast.service.*ServiceImpl.*(..))" id="pc"/>

execution有以下幾種形式

public void cn.itcast.service.UserServiceImpl.save() 具體的某個方法
void cn.itcast.service.UserServiceImpl.save()
* cn.itcast.service.UserServiceImpl.save() 任意返回值
* cn.itcast.service.UserServiceImpl.*() 任意方法名/任意返回值
* cn.itcast.service.*ServiceImpl.*(..) 任意參數/ 任意返回值/ 任意方法名
* cn.itcast.service..*ServiceImpl.*(..) 還會找這個下面的子包

<aop:config>
        <aop:pointcut expression="execution(* com.domin.*Service.*(..))" id="pc"/>
        <aop:aspect ref="advice">
            <aop:before method="before" pointcut-ref="pc"/>
            <aop:around method="around" pointcut-ref="pc"/>
            <aop:after-throwing method="afterException" pointcut-ref="pc"/>
            <aop:after method="after" pointcut-ref="pc"/>
            <aop:after-returning method="afterReturn" pointcut-ref="pc"/>
        </aop:aspect>
</aop:config>

調用順序

1.沒有發生異常的情況下

前置通知
這是環繞通知之前的部分
save method
這是環繞通知之後的部分
後置通知(出現異常也會調用)
後置通知(如果出現異常不會被調用)

2.發生異常的情況下

前置通知
這是環繞通知之前的部分
出現異常了
後置通知(出現異常也會調用)

註解配置實現動態代理

1.導包

2.配置

同樣需要加入 <bean name="userService" class="..."></bean> 和 <bean name="myAdvice" class="...">

3.使用註解來實現代理

4.在配置文件中加入 <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 表示開啟使用註解完成織入

5.測試

spring學習2