9月15日spring笔记
发布时间:
本文字数:1,236 字 阅读完需:约 5 分钟
利用注解进行Bean的自动扫描管理
使用注解注入可以省略set方法
例子:
spring-scan.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描包-->
<context:component-scan base-package="com.scan"></context:component-scan>
</beans>
- 会扫描com.scan包及所有自包下的类
- spring会管理如下规则的类
类上加注解:
@Controller
(controller层 action)
@Service
(service层 model)
@Repository
(dao层)
@Component
(其他层)
四个注解的区别:无
以下注解写在属性之前,见下例
@Value("注入的属性值")
:自动根据类型byType注入
@Autowired
:自动根据类型byType注入
Computer.java
package com.scan;
import org.springframework.stereotype.Component;
@Component("com")
public class Computer {
@value("小米")
private String name;
// @Resource(name = "intel") //根据name注入,不需Qualifier和Autowired
@Qualifier("AMD") //过滤名为AMD的CPU的实现类
@Autowired //自动根据类型byType注入
private CPU cpu;
@Override
public String toString() {
return "Computer{" +
"name='" + name + '\'' +
", cpu=" + cpu +
'}';
}
}
TestScan.java
package com.scan;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestScan {
public static void main(String[] args) {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("spring-scan.xml");
Computer computer = (Computer) ac.getBean("com");
System.out.println(computer);
}
}
Intel.java
package com.scan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Intel implements CPU {
@Value("I9")
private String name;
@Override
public String toString() {
return "Intel{" +
"name='" + name + '\'' +
'}';
}
}
AMD.java
package com.scan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class AMD implements CPU {
@Value("R7")
private String name;
@Override
public String toString() {
return "AMD{" +
"name='" + name + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
输出结果如下:
Computer{name='小米', cpu='R7'}
使用java类写spring配置
使用@Configuration
注解,自动扫描配置使用@ComponentScan
注解
在测试类中使用AnnotationConfigApplicationContext
对象导入配置类,见下例
示例
SpringScanConfig.java
package com.scan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.scan")
public class SpringScanConfig {
}
TestScan.java
package com.scan;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestScan {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringScanConfig.class);
Computer computer = (Computer) ac.getBean("com");
System.out.println(computer);
}
}
代理模式
代理模式:代理模式又叫委托模式,是为某个对象提供一个代理对象,并且由代理对象控制对原对象的访问。
静态代理:目标类和代理类有相同的接口
动态代理:代理类是动态生成的,目标类和代理类可以没有相同的接口
静态代理简单示例
Star.java
package com.zr.proxy;
public interface Star {
//赚钱
void makeMoney(int money);
//秀恩爱
void showLove();
}
BaoQiang.java
package com.zr.proxy;
public class BaoQiang implements Star{
@Override
public void makeMoney(int money) {
System.out.println("宝强赚了"+money+"钱,宝强笑嘿嘿");
}
@Override
public void showLove() {
System.out.println("宝强秀恩爱,别人都羡慕");
}
}
SongZhe.java
package com.zr.proxy;
import java.util.Random;
public class SongZhe implements Star{
private Star star;
public SongZhe(Star star) {
this.star = star;
}
@Override
public void makeMoney(int money) {
System.out.println("宋喆抽成500....");
star.makeMoney(money);
}
@Override
public void showLove() {
boolean r = new Random().nextBoolean();
if(r){
star.showLove();
}
else{
System.out.println("宋喆偷偷找马蓉");
}
}
}
TestStar.java
package com.zr.proxy;
import org.junit.Test;
public class TestStar {
@Test
public void star(){
BaoQiang baoQiang = new BaoQiang();
SongZhe songZhe = new SongZhe(baoQiang);
songZhe.makeMoney(1000);
songZhe.showLove();
}
}
运行结果
宋喆抽成500....
宝强赚了1000钱,宝强笑嘿嘿
宝强秀恩爱,别人都羡慕
动态代理示例
TestStar.java
@Test
public void myStar(){
//生成被代理类对象
Star star = new BaoQiang();
//生成代理类对象
Star proxy = (Star) Proxy.newProxyInstance(star.getClass().getClassLoader(), star.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(proxy.getClass().getName());
if(method.getName().equals("makeMoney")){
args[0] = 1000;
}
return method.invoke(star, args);
}
});
proxy.makeMoney(2000);
System.out.println("proxy==>" + proxy.getClass().getName());
}
java注解
定义一个注解
MyWeb.java
package com.zr.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 定义一个注解
*/
//以下为元注解
@Target({ElementType.TYPE, ElementType.METHOD}) //修饰的注解能放到java类和方法的某一位置
@Retention(RetentionPolicy.RUNTIME) //注解的生效范围(RUNTIME指运行时生效)
public @interface MyWeb {
String value() default "";
String [] url() default {};
}
TestWeb.java
package com.zr.annotation;
import org.junit.Test;
public class TestWeb {
@Test
public void test(){
//tomcat收到前端请求 /user/web, 需要判断交给哪个servlet来处理
//tomcat遍历所有类,判断哪些类加了 MyWeb注解
Class<?> clazz = UserWeb.class;
MyWeb myWeb = clazz.getAnnotation(MyWeb.class);
System.out.println(myWeb.value());
//tomcat发现UserWeb类的MyWeb注解,value属性值和/user/web匹配,进入后续处理....
}
}
AOP (面向切面编程)
AOP(Aspect-Oriented Programming, 面向切面编程): 是一种新的方法论, 是对传统 OOP(Object-Oriented Programming, 面向对象编程) 的补充
切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象。事务和日志管理是 J2EE 应用中一个关于横切关注点的很好的例子。 在 Spring AOP 中,切面可以使用通用类(基于模式的风格) 或者在普通类中以 @Aspect 标注(@AspectJ 风格)来实现;
示例
spring-aop.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="man" class="com.aop.Man"></bean>
<bean id="fbi" class="com.aop.FBI"></bean>
<aop:config>
<!-- 切面规则 执行在Man的任意方法,参数为任意-->
<aop:pointcut id="pointcut" expression="execution(* com.aop.Man.*(..))"/>
<aop:aspect ref="fbi">
<!-- fbi这个bean的before方法 :before为前置通知-->
<aop:before method="before" pointcut-ref="pointcut"></aop:before>
</aop:aspect>
</aop:config>
</beans>
FBI.java
package com.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import java.util.Arrays;
public class FBI {
public void before(JoinPoint joinPoint){
Object obj = joinPoint.getTarget();
System.out.println("目标对象: "+ obj.getClass().getName());
Object[] args = joinPoint.getArgs();
System.out.println("目标对象方法参数: "+ Arrays.toString(args));
Signature signature = joinPoint.getSignature();
System.out.println("目标对象的方法: "+signature.getName());
}
}
Man.java
package com.aop;
public class Man {
private String name = "大壮";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void qq(String toName){
System.out.println(this.name + "在和[" + toName + "]聊QQ");
}
public void mm(){
System.out.println(this.name + "在聊MM");
}
}
TestAop.java
package com.aop;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAop {
private ClassPathXmlApplicationContext ac;
@Before
public void init(){
ac = new ClassPathXmlApplicationContext("spring-aop.xml");
}
@Test
public void testBefore(){
Man man = ac.getBean(Man.class);
man.qq("小美");
man.mm();
}
@After
public void destroy(){
ac.close();
}
}
输出结果:
目标对象: com.aop.Man
目标对象方法参数: [小美]
目标对象的方法: qq
大壮在和[小美]聊QQ
目标对象: com.aop.Man
目标对象方法参数: []
目标对象的方法: mm
大壮在聊MM