Spring(下)实践 与 注解解析

1.(Spring IOC)写一个商店模型,包括老板,员工

Shop Boss与Staff:     

 

每个类全部添加  ”  @Component   “   注解

 老板和员工都创建name变量,增加无参构造并附名为”老板“”员工“,还有name的get、set方法

例如 老板Boss:

package org.example.ShopDemo;

import org.springframework.stereotype.Component;

@Component
public class Staff {

    public String name;

    //    无参构造
    public Staff(){
        this.name = "员工";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

在Shop里 @ResourceBossStaff , 就可以自动装配了

并且,创建一个work方法:

package org.example.ShopDemo;

import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component
public class Shop {
    @Resource
    private Boss boss;
    @Resource
    private Staff staff;

    public void work(String task){
        System.out.println(boss.getName() + "派遣" + staff.getName() + task);
    }
}

回到之前的app类里增加与Shop的连接,并使用一下work方法:

package org.example;
import org.example.ShopDemo.Shop;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class app {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext ("beans.xml");
        Shop shop = (Shop) context.getBean("shop");
        shop.work("出差");
    }
}

结果:          

2.(Spring AOP)进入店铺申请机制

老板和员工需要向店铺系统提交报告( report )才能进入店铺

老板员工分别赋予report属性,创建进入店铺方法,员工可以设置一个“不允许”

public String report = "允许进入";

public void enterShop(){
        System.out.println(getName() + "进入店铺");
    }

 使用进入店铺方法会先被AOP截获再执行,

创建aop目录及文件:

 写起来比较复杂,先写个  

public void validate(){}

然后再在它上面添加

@Around("execution(public * org.example.ShopDemo.*.enterShop(..))")

后面再写完 {  } 内的内容,最后再向上抛出异常。

package org.example.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;

@Aspect
@Component
public class ReportAspect {
    @Around("execution(public * org.example.ShopDemo.*.enterShop(..))")
    public void validate(ProceedingJoinPoint joinPoint) throws Throwable {
        Object object = joinPoint.getThis();
        Method method = object.getClass().getMethod("getReport");
        String report = (String) method.invoke(object);
        if(report.equals("允许进入")){
            joinPoint.proceed();
        }
    }

}

完善一下main,老板员工都申请进入店铺:

public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext ("beans.xml");
        Shop shop = (Shop) context.getBean("shop");
        shop.work("出差");
        Boss boss = (Boss) context.getBean("boss");
        boss.enterShop();
        Staff staff = (Staff) context.getBean("staff");
        staff.enterShop();
    }

员工的任务是出差,应该不被允许进入店铺,员工的report设置的是“不允许”,aop判断自然不通过:

 

3.(Spring Conf)给店铺配置房屋

首先是熟悉的创建包和类

先写House的属性,包括面积和高度,构造方法以及覆写toString

package org.example.conf;

public class House {
    private int area;
    private int height;

    @Override
    public String toString() {
        return "House{" +
                "area=" + area +
                ", height=" + height +
                '}';
    }

    public House(int area, int height){
        this.area = area;
        this.height = height;

    }
}

配置Conf,@Configuration注解,通过@Bean声明House属性

package org.example.conf;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ShopConf {
    @Bean
    public House generate(){
        return new House(200,10);
    }
}

shop中增加house这个属性,构造方法需要@Autowired

    private House house;

    @Autowired
    public Shop(House house) {
        this.house = house;
    }

    public House getHouse() {
        return house;
    }

    public void setHouse(House house) {
        this.house = house;
    }

main里输出运行一下

System.out.println(shop.getHouse().toString());

结果: House{area=200, height=10}

4.常用注解的总结

一 注解分类:

1.用于创建对象的注解

1.Component(主要作用于类)

2.Service(下有示例)

3.Repository(声明存 读写数据操作 的对象)

4.Controller(声明 提供接口)

5.Bean(主要作用于方法)

2.用于注入数据的注解

1.Autowired(默认通过类型查找)

2.Qualifier(可以和Autowired结合,等于Resource)

3.Resource(默认通过名称查找,比如@Resource(name = "BigBoss")

3.用于改变Bean作用范围的注解

1.Scope(下有示例)

4.与Bean生命周期相关的注解(下有示例)

1.PreDestory(毁灭时执行)

2.PostConstruct(创建时执行)

二 部分注解用法

1. (Service)写一个采购服务

 ShopService ,用 @Service 注解,并声明一个采购方法;

package org.example.Service;

import org.springframework.stereotype.Service;

@Service
public class ShopService {
    //声明一个采购方法
    public void purchase(){
        System.out.println("采购货物");
    }
}

TestService,也用 @Service 注解,用@Resource引进来ShopService,

并声明一个test方法用来测试采购方法

package org.example.Service;

import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class TestService {
    @Resource
    private ShopService shopService;
    public void test(){
        shopService.purchase();
    }
}

main里测试一下,结果为“采购货物”

TestService testService = (TestService) context.getBean("testService");
testService.test();

2.Scope

每次引用Staff都创建一个新的Staff,还是一直只用一个Staff

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
//每次引用Staff都创建一个新的Staff,还是一直只用一个Staff
@Scope("prototype")//singleton
public class Staff {
//..........
}

配合Staff可以在输出里看出效果

public Staff(){
        this.name = "员工";
        System.out.println("来了一个新员工");
    }

3.PreDestory和PostConstruct

在boss中添加两个方法,分别beans开始时执行和结束时执行,结束需要在main最后加一个

context.close();
    @PostConstruct
    public void construct(){
        System.out.println("老板起床");
    }
    @PreDestroy
    public void destroy(){
        System.out.println("老板离开店铺");
    }

以上示例输出结果be like :

老板起床
来了一个新员工
老板派遣员工出差
老板进入店铺
来了一个新员工
House{area=200, height=10}
采购货物
老板离开店铺

进程已结束,退出代码 0

5.自定义注解

1.@Target

规定注解的作用目标

@Target({ElementType.METHOD})
//TYPE,FIELD,METHOD, PARAMETER,CONSTRUCTOR......

2.@Retention

注解的保留策略

@Retention(RetentionPolicy.RUNTIME)
//注解保留策略:SOURCE编译后丢弃,CLASS只保留在class中 运行时就丢弃,RUNTIME运行时也会被保留

3.@Inherited

子类可以继承父类标注的注解

@Inherited//是否可以被继承

示例:老板进入店铺之后视察

随便取个名字

 

 写一下,配置几种注释,注解里的变量比如我随便写的value,使用时可以被获取,不设置就不用获取。

package org.example.annotation;

import java.lang.annotation.*;

@Target({ElementType.METHOD})
//TYPE,FIELD,METHOD, PARAMETER,CONSTRUCTOR......
@Retention(RetentionPolicy.RUNTIME)
//注解保留策略SOURCE编译后丢弃,CLASS只保留在class中 运行时就丢弃,RUNTIME运行时也会被保留
@Inherited//是否可以被继承
public @interface Hahahaha {
//    注解的变量,使用时可以被获取
    String value();

}

 在aop里写一下新注解相关的 新 方法执行判断

    @Around("@annotation(org.example.annotation.Hahahaha)")
    public void annotation(ProceedingJoinPoint joinPoint) throws Throwable {
        Object object = joinPoint.getThis();
        Method method = object.getClass().getMethod("getReport");
        String report = (String) method.invoke(object);
        if(report.equals("允许进入")){
            joinPoint.proceed();
        }
    }

 在boss中添加一个自定义注解的视察方法,此处可以使用变量,没设置就不用获取。

//自定义注解
    @Hahahaha(value = "心情不错")
    public void enterRepo(){
        System.out.println(getName() + "上班视察");
    }

main里运行

        Boss boss = (Boss) context.getBean("boss");
        boss.enterShop();
        boss.enterRepo();

结果:

老板进入店铺
老板上班视察

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值