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里 @Resource 出 Boss 和 Staff , 就可以自动装配了
并且,创建一个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();
结果:
老板进入店铺
老板上班视察